changeset 764:f57c52738f90 HEAD

Renamed IBuffer and OBuffer to IStream and OStream which describes their functionality better. I tried to keep the variable names and comments also sensible.
author Timo Sirainen <tss@iki.fi>
date Fri, 06 Dec 2002 03:09:22 +0200
parents bbf682857b4a
children 553f050c8313
files src/auth/login-connection.c src/auth/master.c src/auth/userinfo-passwd-file.c src/imap/client.c src/imap/client.h src/imap/cmd-append.c src/imap/cmd-fetch.c src/imap/cmd-search.c src/imap/cmd-sort.c src/imap/mail-storage-callbacks.c src/lib-imap/imap-bodystructure.c src/lib-imap/imap-bodystructure.h src/lib-imap/imap-envelope.c src/lib-imap/imap-message-cache.c src/lib-imap/imap-message-cache.h src/lib-imap/imap-parser.c src/lib-imap/imap-parser.h src/lib-index/mail-index-update-cache.c src/lib-index/mail-index-update.c src/lib-index/mail-index-util.c src/lib-index/mail-index.h src/lib-index/maildir/maildir-index.h src/lib-index/maildir/maildir-open.c src/lib-index/maildir/maildir-update.c src/lib-index/mbox/mbox-append.c src/lib-index/mbox/mbox-index.c src/lib-index/mbox/mbox-index.h src/lib-index/mbox/mbox-lock.c src/lib-index/mbox/mbox-open.c src/lib-index/mbox/mbox-rebuild.c src/lib-index/mbox/mbox-rewrite.c src/lib-index/mbox/mbox-sync-full.c src/lib-index/mbox/mbox-sync.c src/lib-mail/message-body-search.c src/lib-mail/message-body-search.h src/lib-mail/message-parser.c src/lib-mail/message-parser.h src/lib-mail/message-send.c src/lib-mail/message-send.h src/lib-mail/message-size.c src/lib-mail/message-size.h src/lib-storage/index/index-copy.c src/lib-storage/index/index-fetch-section.c src/lib-storage/index/index-fetch.c src/lib-storage/index/index-fetch.h src/lib-storage/index/index-msgcache.c src/lib-storage/index/index-save.c src/lib-storage/index/index-search.c src/lib-storage/index/index-sort.c src/lib-storage/index/index-sort.h src/lib-storage/index/index-storage.h src/lib-storage/index/maildir/maildir-save.c src/lib-storage/index/maildir/maildir-storage.h src/lib-storage/index/mbox/mbox-expunge.c src/lib-storage/index/mbox/mbox-save.c src/lib-storage/index/mbox/mbox-storage.h src/lib-storage/mail-sort.c src/lib-storage/mail-storage.h src/lib/Makefile.am src/lib/ibuffer-data.c src/lib/ibuffer-file.c src/lib/ibuffer-internal.h src/lib/ibuffer-mmap.c src/lib/ibuffer.c src/lib/ibuffer.h src/lib/iobuffer-internal.h src/lib/iobuffer.c src/lib/iostream-internal.h src/lib/iostream.c src/lib/istream-data.c src/lib/istream-file.c src/lib/istream-internal.h src/lib/istream-mmap.c src/lib/istream.c src/lib/istream.h src/lib/lib.h src/lib/obuffer-file.c src/lib/obuffer-internal.h src/lib/obuffer.c src/lib/obuffer.h src/lib/ostream-file.c src/lib/ostream-internal.h src/lib/ostream.c src/lib/ostream.h src/login/auth-connection.c src/login/client-authenticate.c src/login/client.c src/login/client.h src/master/auth-process.c src/master/login-process.c src/master/settings.c
diffstat 91 files changed, 2736 insertions(+), 2720 deletions(-) [+]
line wrap: on
line diff
--- a/src/auth/login-connection.c	Fri Dec 06 00:37:33 2002 +0200
+++ b/src/auth/login-connection.c	Fri Dec 06 03:09:22 2002 +0200
@@ -2,8 +2,8 @@
 
 #include "common.h"
 #include "ioloop.h"
-#include "ibuffer.h"
-#include "obuffer.h"
+#include "istream.h"
+#include "ostream.h"
 #include "network.h"
 #include "login-connection.h"
 
@@ -20,8 +20,8 @@
 
 	int fd;
 	IO io;
-	IBuffer *inbuf;
-	OBuffer *outbuf;
+	IStream *input;
+	OStream *output;
         AuthRequestType type;
 };
 
@@ -35,10 +35,10 @@
 
 	i_assert(reply->data_size <= AUTH_MAX_REPLY_DATA_SIZE);
 
-	if (o_buffer_send(conn->outbuf, reply, sizeof(AuthReplyData)) < 0)
+	if (o_stream_send(conn->output, reply, sizeof(AuthReplyData)) < 0)
 		login_connection_destroy(conn);
 	else if (reply->data_size > 0) {
-		if (o_buffer_send(conn->outbuf, data, reply->data_size) < 0)
+		if (o_stream_send(conn->output, data, reply->data_size) < 0)
 			login_connection_destroy(conn);
 	}
 }
@@ -50,7 +50,7 @@
         unsigned char *data;
 	size_t size;
 
-	switch (i_buffer_read(conn->inbuf)) {
+	switch (i_stream_read(conn->input)) {
 	case 0:
 		return;
 	case -1:
@@ -65,7 +65,7 @@
 		return;
 	}
 
-	data = i_buffer_get_modifyable_data(conn->inbuf, &size);
+	data = i_stream_get_modifyable_data(conn->input, &size);
 	if (size < sizeof(AuthRequestType))
 		return;
 
@@ -83,7 +83,7 @@
 			return;
 
 		memcpy(&request, data, sizeof(request));
-		i_buffer_skip(conn->inbuf, sizeof(request));
+		i_stream_skip(conn->input, sizeof(request));
 
 		/* we have a full init request */
 		auth_init_request(&request, request_callback, conn);
@@ -98,7 +98,7 @@
 		if (size < sizeof(request) + request.data_size)
 			return;
 
-		i_buffer_skip(conn->inbuf, sizeof(request) + request.data_size);
+		i_stream_skip(conn->input, sizeof(request) + request.data_size);
 
 		/* we have a full continued request */
 		auth_continue_request(&request, data + sizeof(request),
@@ -122,9 +122,9 @@
 	conn = i_new(LoginConnection, 1);
 
 	conn->fd = fd;
-	conn->inbuf = i_buffer_create_file(fd, default_pool, MAX_INBUF_SIZE,
+	conn->input = i_stream_create_file(fd, default_pool, MAX_INBUF_SIZE,
 					   FALSE);
-	conn->outbuf = o_buffer_create_file(fd, default_pool, MAX_OUTBUF_SIZE,
+	conn->output = o_stream_create_file(fd, default_pool, MAX_OUTBUF_SIZE,
 					    IO_PRIORITY_DEFAULT, FALSE);
 	conn->io = io_add(fd, IO_READ, login_input, conn);
 	conn->type = AUTH_REQUEST_NONE;
@@ -132,7 +132,7 @@
 	conn->next = connections;
 	connections = conn;
 
-	if (o_buffer_send(conn->outbuf, &auth_init_data,
+	if (o_stream_send(conn->output, &auth_init_data,
 			  sizeof(auth_init_data)) < 0) {
 		login_connection_destroy(conn);
 		conn = NULL;
@@ -152,8 +152,8 @@
 		}
 	}
 
-	i_buffer_unref(conn->inbuf);
-	o_buffer_unref(conn->outbuf);
+	i_stream_unref(conn->input);
+	o_stream_unref(conn->output);
 
 	io_remove(conn->io);
 	net_disconnect(conn->fd);
--- a/src/auth/master.c	Fri Dec 06 00:37:33 2002 +0200
+++ b/src/auth/master.c	Fri Dec 06 03:09:22 2002 +0200
@@ -2,7 +2,7 @@
 
 #include "common.h"
 #include "ioloop.h"
-#include "obuffer.h"
+#include "ostream.h"
 #include "network.h"
 #include "cookie.h"
 #include "master.h"
@@ -11,7 +11,7 @@
 
 static AuthCookieReplyData failure_reply;
 
-static OBuffer *outbuf;
+static OStream *output;
 static IO io_master;
 
 static unsigned int master_pos;
@@ -35,7 +35,7 @@
 	}
 
 	reply->id = request->id;
-	switch (o_buffer_send(outbuf, reply, sizeof(AuthCookieReplyData))) {
+	switch (o_stream_send(output, reply, sizeof(AuthCookieReplyData))) {
 	case -2:
 		i_fatal("Master transmit buffer full, aborting");
 	case -1:
@@ -72,7 +72,7 @@
 	memset(&failure_reply, 0, sizeof(failure_reply));
 
 	master_pos = 0;
-	outbuf = o_buffer_create_file(MASTER_SOCKET_FD, default_pool,
+	output = o_stream_create_file(MASTER_SOCKET_FD, default_pool,
 				      MAX_OUTBUF_SIZE, IO_PRIORITY_DEFAULT,
 				      FALSE);
 	io_master = io_add(MASTER_SOCKET_FD, IO_READ, master_input, NULL);
@@ -80,6 +80,6 @@
 
 void master_deinit(void)
 {
-	o_buffer_unref(outbuf);
+	o_stream_unref(output);
 	io_remove(io_master);
 }
--- a/src/auth/userinfo-passwd-file.c	Fri Dec 06 00:37:33 2002 +0200
+++ b/src/auth/userinfo-passwd-file.c	Fri Dec 06 03:09:22 2002 +0200
@@ -7,7 +7,7 @@
 
 #include "userinfo-passwd.h"
 
-#include "ibuffer.h"
+#include "istream.h"
 #include "hash.h"
 #include "hex-binary.h"
 #include "md5.h"
@@ -295,15 +295,15 @@
 
 static void passwd_file_parse_file(PasswdFile *pw)
 {
-	IBuffer *inbuf;
+	IStream *input;
 	char *const *args;
 	char *line;
 
-	inbuf = i_buffer_create_file(pw->fd, default_pool, 2048, FALSE);
+	input = i_stream_create_file(pw->fd, default_pool, 2048, FALSE);
 	for (;;) {
-		line = i_buffer_next_line(inbuf);
+		line = i_stream_next_line(input);
 		if (line == NULL) {
-			if (i_buffer_read(inbuf) <= 0)
+			if (i_stream_read(input) <= 0)
 				break;
                         continue;
 		}
@@ -319,7 +319,7 @@
 		}
 		t_pop();
 	}
-	i_buffer_unref(inbuf);
+	i_stream_unref(input);
 }
 
 static PasswdFile *passwd_file_parse(const char *path)
--- a/src/imap/client.c	Fri Dec 06 00:37:33 2002 +0200
+++ b/src/imap/client.c	Fri Dec 06 03:09:22 2002 +0200
@@ -3,8 +3,8 @@
 #include "common.h"
 #include "ioloop.h"
 #include "network.h"
-#include "ibuffer.h"
-#include "obuffer.h"
+#include "istream.h"
+#include "ostream.h"
 #include "commands.h"
 
 #include <stdlib.h>
@@ -36,8 +36,8 @@
 {
 	Client *client = context;
 
-	i_buffer_close(client->inbuf);
-	o_buffer_close(client->outbuf);
+	i_stream_close(client->input);
+	o_stream_close(client->output);
 }
 
 static void client_input_timeout(void *context)
@@ -46,7 +46,7 @@
 
 	client_send_line(my_client, "* BYE Disconnected for inactivity "
 			 "while waiting for command data.");
-	o_buffer_close(client->outbuf);
+	o_stream_close(client->output);
 }
 
 Client *client_create(int hin, int hout, MailStorage *storage)
@@ -54,9 +54,9 @@
 	Client *client;
 
 	client = i_new(Client, 1);
-	client->inbuf = i_buffer_create_file(hin, default_pool,
+	client->input = i_stream_create_file(hin, default_pool,
 					     MAX_INBUF_SIZE, FALSE);
-	client->outbuf = o_buffer_create_file(hout, default_pool, 4096,
+	client->output = o_stream_create_file(hout, default_pool, 4096,
 					      IO_PRIORITY_DEFAULT, FALSE);
 
 	/* always use nonblocking I/O */
@@ -65,15 +65,15 @@
 
 	/* set timeout for reading expected data (eg. APPEND). This is
 	   different from the actual idle time. */
-	i_buffer_set_blocking(client->inbuf, CLIENT_CMDINPUT_TIMEOUT,
+	i_stream_set_blocking(client->input, CLIENT_CMDINPUT_TIMEOUT,
 			      client_input_timeout, client);
 
 	/* set timeout for sending data */
-	o_buffer_set_blocking(client->outbuf, CLIENT_OUTPUT_TIMEOUT,
+	o_stream_set_blocking(client->output, CLIENT_OUTPUT_TIMEOUT,
 			      client_output_timeout, client);
 
 	client->io = io_add(hin, IO_READ, (IOFunc) client_input, client);
-	client->parser = imap_parser_create(client->inbuf, client->outbuf,
+	client->parser = imap_parser_create(client->input, client->output,
 					    MAX_INBUF_SIZE);
         client->last_input = ioloop_time;
 
@@ -87,7 +87,7 @@
 
 void client_destroy(Client *client)
 {
-	o_buffer_flush(client->outbuf);
+	o_stream_flush(client->output);
 
 	if (client->mailbox != NULL)
 		client->mailbox->close(client->mailbox);
@@ -96,8 +96,8 @@
 	imap_parser_destroy(client->parser);
 	io_remove(client->io);
 
-	i_buffer_unref(client->inbuf);
-	o_buffer_unref(client->outbuf);
+	i_stream_unref(client->input);
+	o_stream_unref(client->output);
 
 	i_free(client);
 
@@ -108,35 +108,35 @@
 
 void client_disconnect(Client *client)
 {
-	o_buffer_flush(client->outbuf);
+	o_stream_flush(client->output);
 
-	i_buffer_close(client->inbuf);
-	o_buffer_close(client->outbuf);
+	i_stream_close(client->input);
+	o_stream_close(client->output);
 }
 
 void client_send_line(Client *client, const char *data)
 {
-	if (client->outbuf->closed)
+	if (client->output->closed)
 		return;
 
-	(void)o_buffer_send(client->outbuf, data, strlen(data));
-	(void)o_buffer_send(client->outbuf, "\r\n", 2);
+	(void)o_stream_send(client->output, data, strlen(data));
+	(void)o_stream_send(client->output, "\r\n", 2);
 }
 
 void client_send_tagline(Client *client, const char *data)
 {
 	const char *tag = client->cmd_tag;
 
-	if (client->outbuf->closed)
+	if (client->output->closed)
 		return;
 
 	if (tag == NULL || *tag == '\0')
 		tag = "*";
 
-	(void)o_buffer_send(client->outbuf, tag, strlen(tag));
-	(void)o_buffer_send(client->outbuf, " ", 1);
-	(void)o_buffer_send(client->outbuf, data, strlen(data));
-	(void)o_buffer_send(client->outbuf, "\r\n", 2);
+	(void)o_stream_send(client->output, tag, strlen(tag));
+	(void)o_stream_send(client->output, " ", 1);
+	(void)o_stream_send(client->output, data, strlen(data));
+	(void)o_stream_send(client->output, "\r\n", 2);
 }
 
 void client_send_command_error(Client *client, const char *msg)
@@ -220,7 +220,7 @@
 
 static void client_command_finished(Client *client)
 {
-	client->inbuf_skip_line = TRUE;
+	client->input_skip_line = TRUE;
         client_reset_command(client);
 }
 
@@ -231,18 +231,17 @@
 	const unsigned char *data;
 	size_t i, data_size;
 
-	/* get the beginning of data in input buffer */
-	data = i_buffer_get_data(client->inbuf, &data_size);
+	data = i_stream_get_data(client->input, &data_size);
 
 	for (i = 0; i < data_size; i++) {
 		if (data[i] == '\n') {
-			client->inbuf_skip_line = FALSE;
-			i_buffer_skip(client->inbuf, i+1);
+			client->input_skip_line = FALSE;
+			i_stream_skip(client->input, i+1);
 			break;
 		}
 	}
 
-	return !client->inbuf_skip_line;
+	return !client->input_skip_line;
 }
 
 static int client_handle_input(Client *client)
@@ -257,7 +256,7 @@
 		return FALSE;
 	}
 
-	if (client->inbuf_skip_line) {
+	if (client->input_skip_line) {
 		/* we're just waiting for new line.. */
 		if (!client_skip_line(client))
 			return FALSE;
@@ -306,7 +305,7 @@
 {
 	client->last_input = ioloop_time;
 
-	switch (i_buffer_read(client->inbuf)) {
+	switch (i_stream_read(client->input)) {
 	case -1:
 		/* disconnected */
 		client_destroy(client);
@@ -315,19 +314,19 @@
 		/* parameter word is longer than max. input buffer size.
 		   this is most likely an error, so skip the new data
 		   until newline is found. */
-		client->inbuf_skip_line = TRUE;
+		client->input_skip_line = TRUE;
 
 		client_send_command_error(client, "Too long argument.");
 		client_command_finished(client);
 		break;
 	}
 
-	o_buffer_cork(client->outbuf);
+	o_stream_cork(client->output);
 	while (client_handle_input(client))
 		;
-	o_buffer_flush(client->outbuf);
+	o_stream_flush(client->output);
 
-	if (client->outbuf->closed)
+	if (client->output->closed)
 		client_destroy(client);
 }
 
--- a/src/imap/client.h	Fri Dec 06 00:37:33 2002 +0200
+++ b/src/imap/client.h	Fri Dec 06 03:09:22 2002 +0200
@@ -11,8 +11,8 @@
 struct _Client {
 	int socket;
 	IO io;
-	IBuffer *inbuf;
-	OBuffer *outbuf;
+	IStream *input;
+	OStream *output;
 
 	MailStorage *storage;
 	Mailbox *mailbox;
@@ -29,7 +29,7 @@
 	unsigned int cmd_uid:1; /* used UID command */
 	unsigned int sync_flags_send_uid:1;
 	unsigned int rawlog:1;
-	unsigned int inbuf_skip_line:1; /* skip all the data until we've
+	unsigned int input_skip_line:1; /* skip all the data until we've
 					   found a new line */
 };
 
--- a/src/imap/cmd-append.c	Fri Dec 06 00:37:33 2002 +0200
+++ b/src/imap/cmd-append.c	Fri Dec 06 03:09:22 2002 +0200
@@ -2,7 +2,7 @@
 
 #include "common.h"
 #include "ioloop.h"
-#include "obuffer.h"
+#include "ostream.h"
 #include "commands.h"
 #include "imap-parser.h"
 #include "imap-date.h"
@@ -126,13 +126,13 @@
 		return TRUE;
 	}
 
-	o_buffer_send(client->outbuf, "+ OK\r\n", 6);
-	o_buffer_flush(client->outbuf);
+	o_stream_send(client->output, "+ OK\r\n", 6);
+	o_stream_flush(client->output);
 
 	/* save the mail */
 	failed = !box->save(box, flags, custom_flags,
 			    internal_date, timezone_offset,
-			    client->inbuf, msg_size);
+			    client->input, msg_size);
 	box->close(box);
 
 	if (failed) {
--- a/src/imap/cmd-fetch.c	Fri Dec 06 00:37:33 2002 +0200
+++ b/src/imap/cmd-fetch.c	Fri Dec 06 03:09:22 2002 +0200
@@ -264,7 +264,7 @@
 
 	/* fetch it */
 	if (client->mailbox->fetch(client->mailbox, &data,
-				   client->outbuf, &all_found)) {
+				   client->output, &all_found)) {
 		/* NOTE: syncing isn't allowed here */
                 client_sync_without_expunges(client);
 		client_send_tagline(client, all_found ? "OK Fetch completed." :
--- a/src/imap/cmd-search.c	Fri Dec 06 00:37:33 2002 +0200
+++ b/src/imap/cmd-search.c	Fri Dec 06 03:09:22 2002 +0200
@@ -51,7 +51,7 @@
 	} else {
 		if (client->mailbox->search(client->mailbox, charset,
 					    sargs, NULL,
-					    client->outbuf, client->cmd_uid)) {
+					    client->output, client->cmd_uid)) {
 			/* NOTE: syncing isn't allowed here */
 			client_sync_without_expunges(client);
 			client_send_tagline(client, "OK Search completed.");
--- a/src/imap/cmd-sort.c	Fri Dec 06 00:37:33 2002 +0200
+++ b/src/imap/cmd-sort.c	Fri Dec 06 03:09:22 2002 +0200
@@ -120,7 +120,7 @@
 	} else {
 		if (client->mailbox->search(client->mailbox, charset,
 					    sargs, sorting,
-					    client->outbuf, client->cmd_uid)) {
+					    client->output, client->cmd_uid)) {
 			/* NOTE: syncing is allowed when returning UIDs */
 			if (client->cmd_uid)
 				client_sync_full(client);
--- a/src/imap/mail-storage-callbacks.c	Fri Dec 06 00:37:33 2002 +0200
+++ b/src/imap/mail-storage-callbacks.c	Fri Dec 06 03:09:22 2002 +0200
@@ -1,7 +1,7 @@
 /* Copyright (C) 2002 Timo Sirainen */
 
 #include "common.h"
-#include "obuffer.h"
+#include "ostream.h"
 #include "imap-util.h"
 #include "commands-util.h"
 
@@ -19,7 +19,7 @@
 	Client *client = context;
 
 	client_send_line(client, t_strconcat("* OK ", text, NULL));
-	o_buffer_flush(client->outbuf);
+	o_stream_flush(client->output);
 }
 
 static void notify_no(Mailbox *mailbox __attr_unused__,
@@ -28,7 +28,7 @@
 	Client *client = context;
 
 	client_send_line(client, t_strconcat("* NO ", text, NULL));
-	o_buffer_flush(client->outbuf);
+	o_stream_flush(client->output);
 }
 
 static void expunge(Mailbox *mailbox, unsigned int seq, void *context)
--- a/src/lib-imap/imap-bodystructure.c	Fri Dec 06 00:37:33 2002 +0200
+++ b/src/lib-imap/imap-bodystructure.c	Fri Dec 06 03:09:22 2002 +0200
@@ -1,7 +1,7 @@
 /* Copyright (C) 2002 Timo Sirainen */
 
 #include "lib.h"
-#include "ibuffer.h"
+#include "istream.h"
 #include "temp-string.h"
 #include "rfc822-tokenize.h"
 #include "message-parser.h"
@@ -220,20 +220,20 @@
 	t_pop();
 }
 
-static void part_parse_headers(MessagePart *part, IBuffer *inbuf,
+static void part_parse_headers(MessagePart *part, IStream *input,
 			       uoff_t start_offset, Pool pool)
 {
 	while (part != NULL) {
 		/* note that we want to parse the header of all
 		   the message parts, multiparts too. */
-		i_assert(part->physical_pos >= inbuf->v_offset - start_offset);
-		i_buffer_skip(inbuf, part->physical_pos -
-			      (inbuf->v_offset - start_offset));
+		i_assert(part->physical_pos >= input->v_offset - start_offset);
+		i_stream_skip(input, part->physical_pos -
+			      (input->v_offset - start_offset));
 
-		message_parse_header(part, inbuf, NULL, parse_header, pool);
+		message_parse_header(part, input, NULL, parse_header, pool);
 
 		if (part->children != NULL) {
-			part_parse_headers(part->children, inbuf,
+			part_parse_headers(part->children, input,
 					   start_offset, pool);
 		}
 
@@ -426,15 +426,15 @@
 }
 
 const char *imap_part_get_bodystructure(Pool pool, MessagePart **part,
-					IBuffer *inbuf, int extended)
+					IStream *input, int extended)
 {
 	uoff_t start_offset;
 
 	if (*part == NULL)
-		*part = message_parse(pool, inbuf, parse_header, pool);
+		*part = message_parse(pool, input, parse_header, pool);
 	else {
-		start_offset = inbuf->v_offset;
-		part_parse_headers(*part, inbuf, start_offset, pool);
+		start_offset = input->v_offset;
+		part_parse_headers(*part, input, start_offset, pool);
 	}
 
 	return part_get_bodystructure(*part, extended);
@@ -584,7 +584,7 @@
 
 const char *imap_body_parse_from_bodystructure(const char *bodystructure)
 {
-	IBuffer *inbuf;
+	IStream *input;
 	ImapParser *parser;
 	ImapArg *args;
 	TempString *str;
@@ -595,10 +595,10 @@
 	len = strlen(bodystructure);
 	str = t_string_new(len);
 
-	inbuf = i_buffer_create_from_data(data_stack_pool, bodystructure, len);
-	(void)i_buffer_read(inbuf);
+	input = i_stream_create_from_data(data_stack_pool, bodystructure, len);
+	(void)i_stream_read(input);
 
-	parser = imap_parser_create(inbuf, NULL, 0);
+	parser = imap_parser_create(input, NULL, 0);
 	ret = imap_parser_read_args(parser, 0, IMAP_PARSE_FLAG_NO_UNESCAPE,
 				    &args);
 
@@ -611,6 +611,6 @@
 		i_error("Error parsing IMAP bodystructure: %s", bodystructure);
 
 	imap_parser_destroy(parser);
-	i_buffer_unref(inbuf);
+	i_stream_unref(input);
 	return value;
 }
--- a/src/lib-imap/imap-bodystructure.h	Fri Dec 06 00:37:33 2002 +0200
+++ b/src/lib-imap/imap-bodystructure.h	Fri Dec 06 03:09:22 2002 +0200
@@ -4,7 +4,7 @@
 /* If *part is non-NULL, it's used as base for building the body structure.
    Otherwise it's set to the root MessagePart and parsed. */
 const char *imap_part_get_bodystructure(Pool pool, MessagePart **part,
-					IBuffer *inbuf, int extended);
+					IStream *input, int extended);
 
 /* Return BODY part from BODYSTRUCTURE */
 const char *imap_body_parse_from_bodystructure(const char *bodystructure);
--- a/src/lib-imap/imap-envelope.c	Fri Dec 06 00:37:33 2002 +0200
+++ b/src/lib-imap/imap-envelope.c	Fri Dec 06 03:09:22 2002 +0200
@@ -1,7 +1,7 @@
 /* Copyright (C) 2002 Timo Sirainen */
 
 #include "lib.h"
-#include "ibuffer.h"
+#include "istream.h"
 #include "temp-string.h"
 #include "rfc822-address.h"
 #include "imap-parser.h"
@@ -236,7 +236,7 @@
 
 const char *imap_envelope_parse(const char *envelope, ImapEnvelopeField field)
 {
-	IBuffer *inbuf;
+	IStream *input;
 	ImapParser *parser;
 	ImapArg *args;
 	const char *value;
@@ -244,11 +244,11 @@
 
 	i_assert(field < IMAP_ENVELOPE_FIELDS);
 
-	inbuf = i_buffer_create_from_data(data_stack_pool, envelope,
+	input = i_stream_create_from_data(data_stack_pool, envelope,
 					  strlen(envelope));
-	parser = imap_parser_create(inbuf, NULL, 0);
+	parser = imap_parser_create(input, NULL, 0);
 
-	(void)i_buffer_read(inbuf);
+	(void)i_stream_read(input);
 	ret = imap_parser_read_args(parser, field+1, 0, &args);
 	if (ret > (int)field) {
 		value = imap_envelope_parse_arg(&args[field], field, envelope);
@@ -258,6 +258,6 @@
 	}
 
 	imap_parser_destroy(parser);
-	i_buffer_unref(inbuf);
+	i_stream_unref(input);
 	return value;
 }
--- a/src/lib-imap/imap-message-cache.c	Fri Dec 06 00:37:33 2002 +0200
+++ b/src/lib-imap/imap-message-cache.c	Fri Dec 06 03:09:22 2002 +0200
@@ -1,7 +1,7 @@
 /* Copyright (C) 2002 Timo Sirainen */
 
 #include "lib.h"
-#include "ibuffer.h"
+#include "istream.h"
 #include "temp-string.h"
 #include "mmap-util.h"
 #include "message-parser.h"
@@ -50,7 +50,7 @@
 	int messages_count;
 
 	CachedMessage *open_msg;
-	IBuffer *open_inbuf;
+	IStream *open_stream;
 
 	void *context;
 };
@@ -161,23 +161,24 @@
 	}
 }
 
-static int imap_msgcache_get_inbuf(ImapMessageCache *cache, uoff_t offset)
+static int imap_msgcache_get_stream(ImapMessageCache *cache, uoff_t offset)
 {
-	if (cache->open_inbuf == NULL)
-		cache->open_inbuf = cache->iface->open_mail(cache->context);
-	else if (offset < cache->open_inbuf->v_offset) {
+	if (cache->open_stream == NULL)
+		cache->open_stream = cache->iface->open_mail(cache->context);
+	else if (offset < cache->open_stream->v_offset) {
 		/* need to rewind */
-		cache->open_inbuf =
-			cache->iface->inbuf_rewind(cache->open_inbuf,
-						   cache->context);
+		cache->open_stream =
+			cache->iface->stream_rewind(cache->open_stream,
+						    cache->context);
 	}
 
-	if (cache->open_inbuf == NULL)
+	if (cache->open_stream == NULL)
 		return FALSE;
 
-	i_assert(offset >= cache->open_inbuf->v_offset);
+	i_assert(offset >= cache->open_stream->v_offset);
 
-	i_buffer_skip(cache->open_inbuf, offset - cache->open_inbuf->v_offset);
+	i_stream_skip(cache->open_stream,
+		      offset - cache->open_stream->v_offset);
 	return TRUE;
 }
 
@@ -206,12 +207,12 @@
 	    msg->cached_bodystructure == NULL) {
 		value = cache->iface->get_cached_field(IMAP_CACHE_BODYSTRUCTURE,
 						       cache->context);
-		if (value == NULL && imap_msgcache_get_inbuf(cache, 0)) {
+		if (value == NULL && imap_msgcache_get_stream(cache, 0)) {
 			msg_get_part(cache);
 
 			value = imap_part_get_bodystructure(msg->pool,
 							    &msg->part,
-							    cache->open_inbuf,
+							    cache->open_stream,
 							    TRUE);
 		}
 
@@ -222,7 +223,7 @@
 	if ((fields & IMAP_CACHE_BODY) && msg->cached_body == NULL) {
 		value = cache->iface->get_cached_field(IMAP_CACHE_BODY,
 						       cache->context);
-		if (value == NULL && cache->open_inbuf != NULL) {
+		if (value == NULL && cache->open_stream != NULL) {
 			/* we can generate it from cached BODYSTRUCTURE.
 			   do it only if the file isn't open already, since
 			   this takes more CPU than parsing message headers. */
@@ -234,12 +235,12 @@
 			}
 		}
 
-		if (value == NULL && imap_msgcache_get_inbuf(cache, 0)) {
+		if (value == NULL && imap_msgcache_get_stream(cache, 0)) {
 			msg_get_part(cache);
 
 			value = imap_part_get_bodystructure(msg->pool,
 							    &msg->part,
-							    cache->open_inbuf,
+							    cache->open_stream,
 							    FALSE);
 		}
 
@@ -252,7 +253,7 @@
 						       cache->context);
 		if (value == NULL) {
 			if (msg->envelope == NULL &&
-			    imap_msgcache_get_inbuf(cache, 0)) {
+			    imap_msgcache_get_stream(cache, 0)) {
 				/* envelope isn't parsed yet, do it. header
 				   size is calculated anyway so save it */
 				if (msg->hdr_size == NULL) {
@@ -260,7 +261,7 @@
 							      MessageSize, 1);
 				}
 
-				message_parse_header(NULL, cache->open_inbuf,
+				message_parse_header(NULL, cache->open_stream,
 						     msg->hdr_size,
 						     parse_envelope_header,
 						     msg);
@@ -290,7 +291,7 @@
 	if (fields & IMAP_CACHE_MESSAGE_PART) {
 		msg_get_part(cache);
 
-		if (msg->part == NULL && imap_msgcache_get_inbuf(cache, 0)) {
+		if (msg->part == NULL && imap_msgcache_get_stream(cache, 0)) {
 			/* we need to parse the message */
 			MessageHeaderFunc func;
 
@@ -303,7 +304,7 @@
 				func = NULL;
 			}
 
-			msg->part = message_parse(msg->pool, cache->open_inbuf,
+			msg->part = message_parse(msg->pool, cache->open_stream,
 						  func, msg);
 		} else {
 			failed = TRUE;
@@ -336,8 +337,8 @@
 			}
 		} else {
 			/* need to do some light parsing */
-			if (imap_msgcache_get_inbuf(cache, 0)) {
-				message_get_header_size(cache->open_inbuf,
+			if (imap_msgcache_get_stream(cache, 0)) {
+				message_get_header_size(cache->open_stream,
 							msg->hdr_size);
 			} else {
 				failed = TRUE;
@@ -358,7 +359,7 @@
 	if (fields & IMAP_CACHE_MESSAGE_OPEN) {
 		/* this isn't needed for anything else than pre-opening the
 		   mail and seeing if it fails. */
-		failed = !imap_msgcache_get_inbuf(cache, 0);
+		failed = !imap_msgcache_get_stream(cache, 0);
 	}
 
 	if ((fields & IMAP_CACHE_INTERNALDATE) &&
@@ -410,9 +411,9 @@
 
 void imap_msgcache_close(ImapMessageCache *cache)
 {
-	if (cache->open_inbuf != NULL) {
-		i_buffer_unref(cache->open_inbuf);
-		cache->open_inbuf = NULL;
+	if (cache->open_stream != NULL) {
+		i_stream_unref(cache->open_stream);
+		cache->open_stream = NULL;
 	}
 
 	cache->open_msg = NULL;
@@ -467,7 +468,7 @@
 	return cache->open_msg->internal_date;
 }
 
-int imap_msgcache_get_rfc822(ImapMessageCache *cache, IBuffer **inbuf,
+int imap_msgcache_get_rfc822(ImapMessageCache *cache, IStream **stream,
 			     MessageSize *hdr_size, MessageSize *body_size)
 {
 	CachedMessage *msg;
@@ -476,14 +477,14 @@
 	i_assert(cache->open_msg != NULL);
 
 	msg = cache->open_msg;
-	if (inbuf != NULL) {
+	if (stream != NULL) {
 		if (msg->hdr_size == NULL)
 			cache_fields(cache, IMAP_CACHE_MESSAGE_HDR_SIZE);
 		offset = hdr_size != NULL ? 0 :
 			msg->hdr_size->physical_size;
-		if (!imap_msgcache_get_inbuf(cache, offset))
+		if (!imap_msgcache_get_stream(cache, offset))
 			return FALSE;
-                *inbuf = cache->open_inbuf;
+                *stream = cache->open_stream;
 	}
 
 	if (body_size != NULL) {
@@ -505,7 +506,7 @@
 	return TRUE;
 }
 
-static void get_partial_size(IBuffer *inbuf,
+static void get_partial_size(IStream *stream,
 			     uoff_t virtual_skip, uoff_t max_virtual_size,
 			     MessageSize *partial, MessageSize *dest,
 			     int *cr_skipped)
@@ -514,12 +515,12 @@
 	if (partial->virtual_size > virtual_skip)
 		memset(partial, 0, sizeof(MessageSize));
 	else {
-		i_buffer_skip(inbuf, partial->physical_size);
+		i_stream_skip(stream, partial->physical_size);
 		virtual_skip -= partial->virtual_size;
 	}
 
-	message_skip_virtual(inbuf, virtual_skip, partial, cr_skipped);
-	message_get_body_size(inbuf, dest, max_virtual_size);
+	message_skip_virtual(stream, virtual_skip, partial, cr_skipped);
+	message_get_body_size(stream, dest, max_virtual_size);
 
 	if (*cr_skipped) {
 		dest->virtual_size--;
@@ -531,7 +532,7 @@
 				     uoff_t virtual_skip,
 				     uoff_t max_virtual_size,
 				     int get_header, MessageSize *size,
-                                     IBuffer **inbuf, int *cr_skipped)
+                                     IStream **stream, int *cr_skipped)
 {
 	CachedMessage *msg;
 	uoff_t physical_skip, full_size;
@@ -540,7 +541,7 @@
 	i_assert(cache->open_msg != NULL);
 
 	memset(size, 0, sizeof(MessageSize));
-	*inbuf = NULL;
+	*stream = NULL;
 	*cr_skipped = FALSE;
 
 	msg = cache->open_msg;
@@ -575,7 +576,7 @@
 	if (size_got) {
 		physical_skip = get_header ? 0 : msg->hdr_size->physical_size;
 	} else {
-		if (!imap_msgcache_get_inbuf(cache, 0))
+		if (!imap_msgcache_get_stream(cache, 0))
 			return FALSE;
 
 		if (msg->partial_size == NULL)
@@ -583,7 +584,7 @@
 		if (!get_header)
 			virtual_skip += msg->hdr_size->virtual_size;
 
-		get_partial_size(cache->open_inbuf, virtual_skip,
+		get_partial_size(cache->open_stream, virtual_skip,
 				 max_virtual_size, msg->partial_size, size,
 				 cr_skipped);
 
@@ -591,20 +592,20 @@
 	}
 
 	/* seek to wanted position */
-	if (!imap_msgcache_get_inbuf(cache, physical_skip))
+	if (!imap_msgcache_get_stream(cache, physical_skip))
 		return FALSE;
 
-        *inbuf = cache->open_inbuf;
+        *stream = cache->open_stream;
 	return TRUE;
 }
 
-int imap_msgcache_get_data(ImapMessageCache *cache, IBuffer **inbuf)
+int imap_msgcache_get_data(ImapMessageCache *cache, IStream **stream)
 {
 	i_assert(cache->open_msg != NULL);
 
-	if (!imap_msgcache_get_inbuf(cache, 0))
+	if (!imap_msgcache_get_stream(cache, 0))
 		return FALSE;
 
-        *inbuf = cache->open_inbuf;
+        *stream = cache->open_stream;
 	return TRUE;
 }
--- a/src/lib-imap/imap-message-cache.h	Fri Dec 06 00:37:33 2002 +0200
+++ b/src/lib-imap/imap-message-cache.h	Fri Dec 06 03:09:22 2002 +0200
@@ -26,10 +26,10 @@
 
 typedef struct {
 	/* Open mail for reading. */
-	IBuffer *(*open_mail)(void *context);
-	/* Rewind input buffer to beginning, possibly closing the old buffer
+	IStream *(*open_mail)(void *context);
+	/* Rewind stream to beginning, possibly closing the old stream
 	   if it can't directly be rewinded. */
-	IBuffer *(*inbuf_rewind)(IBuffer *inbuf, void *context);
+	IStream *(*stream_rewind)(IStream *stream, void *context);
 
 	/* Returns field if it's already cached, or NULL. */
 	const char *(*get_cached_field)(ImapCacheField field, void *context);
@@ -56,7 +56,7 @@
 		       uoff_t vp_header_size, uoff_t vp_body_size,
 		       uoff_t full_virtual_size, void *context);
 
-/* Close the IOBuffer for opened message. */
+/* Close the IOStream for opened message. */
 void imap_msgcache_close(ImapMessageCache *cache);
 
 /* Returns the field from cache, or NULL if it's not cached. */
@@ -71,23 +71,23 @@
 /* Returns the internal date of message, or (time_t)-1 if failed. */
 time_t imap_msgcache_get_internal_date(ImapMessageCache *cache);
 
-/* Returns TRUE if successful. If inbuf is not NULL, it's set to point to
+/* Returns TRUE if successful. If stream is not NULL, it's set to point to
    beginning of message, or to beginning of message body if hdr_size is NULL. */
-int imap_msgcache_get_rfc822(ImapMessageCache *cache, IBuffer **inbuf,
+int imap_msgcache_get_rfc822(ImapMessageCache *cache, IStream **stream,
 			     MessageSize *hdr_size, MessageSize *body_size);
 
-/* Returns TRUE if successful. *inbuf is set to point to the first non-skipped
+/* Returns TRUE if successful. *stream is set to point to the first non-skipped
    character. size is set to specify the actual message size in
    virtual_skip..max_virtual_size range. cr_skipped is set to TRUE if first
-   character in inbuf is LF, and we should NOT treat it as CR+LF. */
+   character in stream is LF, and we should NOT treat it as CR+LF. */
 int imap_msgcache_get_rfc822_partial(ImapMessageCache *cache,
 				     uoff_t virtual_skip,
 				     uoff_t max_virtual_size,
 				     int get_header, MessageSize *size,
-				     IBuffer **inbuf, int *cr_skipped);
+				     IStream **stream, int *cr_skipped);
 
-/* Returns TRUE if successful. *inbuf is set to point to beginning of
+/* Returns TRUE if successful. *stream is set to point to beginning of
    message. */
-int imap_msgcache_get_data(ImapMessageCache *cache, IBuffer **inbuf);
+int imap_msgcache_get_data(ImapMessageCache *cache, IStream **stream);
 
 #endif
--- a/src/lib-imap/imap-parser.c	Fri Dec 06 00:37:33 2002 +0200
+++ b/src/lib-imap/imap-parser.c	Fri Dec 06 03:09:22 2002 +0200
@@ -1,8 +1,8 @@
 /* Copyright (C) 2002 Timo Sirainen */
 
 #include "lib.h"
-#include "ibuffer.h"
-#include "obuffer.h"
+#include "istream.h"
+#include "ostream.h"
 #include "imap-parser.h"
 
 #define is_linebreak(c) \
@@ -21,8 +21,8 @@
 struct _ImapParser {
 	/* permanent */
 	Pool pool;
-	IBuffer *inbuf;
-	OBuffer *outbuf;
+	IStream *input;
+	OStream *output;
 	size_t max_literal_size;
         ImapParserFlags flags;
 
@@ -58,15 +58,15 @@
 		parser->list_arg->data.list = parser->cur_list;
 }
 
-ImapParser *imap_parser_create(IBuffer *inbuf, OBuffer *outbuf,
+ImapParser *imap_parser_create(IStream *input, OStream *output,
 			       size_t max_literal_size)
 {
 	ImapParser *parser;
 
 	parser = i_new(ImapParser, 1);
         parser->pool = pool_create("IMAP parser", 8192, FALSE);
-	parser->inbuf = inbuf;
-	parser->outbuf = outbuf;
+	parser->input = input;
+	parser->output = output;
 	parser->max_literal_size = max_literal_size;
 
 	imap_args_realloc(parser, LIST_ALLOC_SIZE);
@@ -112,7 +112,7 @@
 			break;
 	}
 
-        i_buffer_skip(parser->inbuf, i);
+        i_stream_skip(parser->input, i);
 	parser->cur_pos = 0;
 
 	*data += i;
@@ -311,9 +311,9 @@
 			return FALSE;
 		}
 
-		if (parser->outbuf != NULL) {
-			o_buffer_send(parser->outbuf, "+ OK\r\n", 6);
-			o_buffer_flush(parser->outbuf);
+		if (parser->output != NULL) {
+			o_stream_send(parser->output, "+ OK\r\n", 6);
+			o_stream_flush(parser->output);
 		}
 	}
 
@@ -332,7 +332,7 @@
 	/* expecting digits + "}" */
 	for (i = parser->cur_pos; i < data_size; i++) {
 		if (data[i] == '}') {
-			i_buffer_skip(parser->inbuf, i+1);
+			i_stream_skip(parser->input, i+1);
 			return imap_parser_literal_end(parser);
 		}
 
@@ -365,7 +365,7 @@
 
 		if (*data == '\r') {
 			data++; data_size--;
-			i_buffer_skip(parser->inbuf, 1);
+			i_stream_skip(parser->input, 1);
 
 			if (data_size == 0)
 				return FALSE;
@@ -377,7 +377,7 @@
 		}
 
 		data++; data_size--;
-		i_buffer_skip(parser->inbuf, 1);
+		i_stream_skip(parser->input, 1);
 		parser->literal_skip_crlf = FALSE;
 
 		i_assert(parser->cur_pos == 0);
@@ -407,7 +407,7 @@
 	const char *data;
 	size_t data_size;
 
-	data = (const char *) i_buffer_get_data(parser->inbuf, &data_size);
+	data = (const char *) i_stream_get_data(parser->input, &data_size);
 	if (data_size == 0)
 		return FALSE;
 
@@ -468,9 +468,9 @@
 		if (!imap_parser_read_literal(parser, data, data_size))
 			return FALSE;
 
-		/* pass through to parsing data. since inbuf->skip was
+		/* pass through to parsing data. since input->skip was
 		   modified, we need to get the data start position again. */
-		data = (const char *) i_buffer_get_data(parser->inbuf,
+		data = (const char *) i_stream_get_data(parser->input,
 							&data_size);
 
 		/* fall through */
@@ -534,8 +534,7 @@
 	const char *data;
 	size_t i, data_size;
 
-	/* get the beginning of data in input buffer */
-	data = (const char *) i_buffer_get_data(parser->inbuf, &data_size);
+	data = (const char *) i_stream_get_data(parser->input, &data_size);
 
 	for (i = 0; i < data_size; i++) {
 		if (data[i] == ' ' || data[i] == '\r' || data[i] == '\n')
@@ -543,7 +542,7 @@
 	}
 
 	if (i < data_size) {
-		i_buffer_skip(parser->inbuf, i + (data[i] == ' ' ? 1 : 0));
+		i_stream_skip(parser->input, i + (data[i] == ' ' ? 1 : 0));
 		return p_strndup(parser->pool, data, i);
 	} else {
 		return NULL;
@@ -555,8 +554,7 @@
 	const char *data;
 	size_t i, data_size;
 
-	/* get the beginning of data in input buffer */
-	data = (const char *) i_buffer_get_data(parser->inbuf, &data_size);
+	data = (const char *) i_stream_get_data(parser->input, &data_size);
 
 	for (i = 0; i < data_size; i++) {
 		if (data[i] == '\r' || data[i] == '\n')
@@ -564,7 +562,7 @@
 	}
 
 	if (i < data_size) {
-		i_buffer_skip(parser->inbuf, i);
+		i_stream_skip(parser->input, i);
 		return p_strndup(parser->pool, data, i);
 	} else {
 		return NULL;
--- a/src/lib-imap/imap-parser.h	Fri Dec 06 00:37:33 2002 +0200
+++ b/src/lib-imap/imap-parser.h	Fri Dec 06 03:09:22 2002 +0200
@@ -41,18 +41,18 @@
 	ImapArg args[1]; /* variable size */
 };
 
-/* Create new IMAP argument parser. The max. size of inbuf limits the
+/* Create new IMAP argument parser. The max. size of input limits the
    maximum size of each argument. max_literal_size also limits sizes of
    literals which we even try to handle if FLAG_LITERAL_SIZE is not set.
-   outbuf is used for sending command continuation requests for literals. */
-ImapParser *imap_parser_create(IBuffer *inbuf, OBuffer *outbuf,
+   output is used for sending command continuation requests for literals. */
+ImapParser *imap_parser_create(IStream *input, OStream *output,
 			       size_t max_literal_size);
 void imap_parser_destroy(ImapParser *parser);
 
 /* Reset the parser to initial state. */
 void imap_parser_reset(ImapParser *parser);
 
-/* Read a number of arguments. This function doesn't call i_buffer_read(), you
+/* Read a number of arguments. This function doesn't call i_stream_read(), you
    need to do that. Returns number of arguments read (may be less than count
    in case of EOL), -2 if more data is needed or -1 if error occured.
 
--- a/src/lib-index/mail-index-update-cache.c	Fri Dec 06 00:37:33 2002 +0200
+++ b/src/lib-index/mail-index-update-cache.c	Fri Dec 06 03:09:22 2002 +0200
@@ -1,7 +1,7 @@
 /* Copyright (C) 2002 Timo Sirainen */
 
 #include "lib.h"
-#include "ibuffer.h"
+#include "istream.h"
 #include "mail-index.h"
 
 #include <unistd.h>
@@ -10,12 +10,12 @@
 			MailDataField cache_fields)
 {
 	MailIndexUpdate *update;
-	IBuffer *inbuf;
+	IStream *input;
 	time_t internal_date;
 	int failed, deleted;
 
-	inbuf = index->open_mail(index, rec, &internal_date, &deleted);
-	if (inbuf == NULL)
+	input = index->open_mail(index, rec, &internal_date, &deleted);
+	if (input == NULL)
 		return deleted;
 
 	cache_fields &= ~rec->data_fields;
@@ -23,10 +23,10 @@
 	update = index->update_begin(index, rec);
 	index->update_field_raw(update, DATA_HDR_INTERNAL_DATE,
 				&internal_date, sizeof(internal_date));
-	mail_index_update_headers(update, inbuf, cache_fields, NULL, NULL);
+	mail_index_update_headers(update, input, cache_fields, NULL, NULL);
 	failed = !index->update_end(update);
 
-	i_buffer_unref(inbuf);
+	i_stream_unref(input);
 	return !failed;
 }
 
--- a/src/lib-index/mail-index-update.c	Fri Dec 06 00:37:33 2002 +0200
+++ b/src/lib-index/mail-index-update.c	Fri Dec 06 03:09:22 2002 +0200
@@ -1,7 +1,7 @@
 /* Copyright (C) 2002 Timo Sirainen */
 
 #include "lib.h"
-#include "ibuffer.h"
+#include "istream.h"
 #include "ioloop.h"
 #include "rfc822-date.h"
 #include "rfc822-tokenize.h"
@@ -410,7 +410,7 @@
 	}
 }
 
-void mail_index_update_headers(MailIndexUpdate *update, IBuffer *inbuf,
+void mail_index_update_headers(MailIndexUpdate *update, IStream *input,
                                MailDataField cache_fields,
 			       MessageHeaderFunc header_func, void *context)
 {
@@ -452,16 +452,16 @@
 			}
 		}
 
-		start_offset = inbuf->v_offset;
+		start_offset = input->v_offset;
 
 		if (part == NULL) {
-			part = message_parse(pool, inbuf,
+			part = message_parse(pool, input,
 					     update_header_func, &ctx);
 		} else {
 			/* cached, construct the bodystructure using it.
 			   also we need to parse the header.. */
-			i_buffer_seek(inbuf, start_offset);
-			message_parse_header(NULL, inbuf, NULL,
+			i_stream_seek(input, start_offset);
+			message_parse_header(NULL, input, NULL,
 					     update_header_func, &ctx);
 		}
 
@@ -476,9 +476,9 @@
 		    ((update->rec->data_fields | cache_fields) &
 		     DATA_FIELD_BODYSTRUCTURE) == 0) {
 			t_push();
-			i_buffer_seek(inbuf, start_offset);
+			i_stream_seek(input, start_offset);
 			value = imap_part_get_bodystructure(pool, &part,
-							    inbuf, FALSE);
+							    input, FALSE);
 			update->index->update_field(update, DATA_FIELD_BODY,
 						    value, 0);
 			t_pop();
@@ -486,9 +486,9 @@
 
 		if (cache_fields & DATA_FIELD_BODYSTRUCTURE) {
 			t_push();
-			i_buffer_seek(inbuf, start_offset);
+			i_stream_seek(input, start_offset);
 			value = imap_part_get_bodystructure(pool, &part,
-							    inbuf, TRUE);
+							    input, TRUE);
 			update->index->update_field(update,
 						    DATA_FIELD_BODYSTRUCTURE,
 						    value, 0);
@@ -506,10 +506,10 @@
 
 		pool_unref(pool);
 	} else {
-		message_parse_header(NULL, inbuf, &hdr_size,
+		message_parse_header(NULL, input, &hdr_size,
 				     update_header_func, &ctx);
 
-		body_size.physical_size = inbuf->v_limit - inbuf->v_offset;
+		body_size.physical_size = input->v_limit - input->v_offset;
 		if (body_size.physical_size == 0)
                         body_size.virtual_size = 0;
 		else if (update->data_hdr.virtual_size == 0)
--- a/src/lib-index/mail-index-util.c	Fri Dec 06 00:37:33 2002 +0200
+++ b/src/lib-index/mail-index-util.c	Fri Dec 06 03:09:22 2002 +0200
@@ -1,7 +1,7 @@
 /* Copyright (C) 2002 Timo Sirainen */
 
 #include "lib.h"
-#include "ibuffer.h"
+#include "istream.h"
 #include "hostpid.h"
 #include "file-lock.h"
 #include "message-size.h"
--- a/src/lib-index/mail-index.h	Fri Dec 06 00:37:33 2002 +0200
+++ b/src/lib-index/mail-index.h	Fri Dec 06 03:09:22 2002 +0200
@@ -280,11 +280,11 @@
 	   index is opened. */
 	void (*cache_fields_later)(MailIndex *index, MailDataField field);
 
-	/* Open mail file and return it as mmap()ed IBuffer. If we fail,
+	/* Open mail file and return it as mmap()ed IStream. If we fail,
 	   we return NULL and set deleted = TRUE if failure was because the
 	   mail was just deleted (ie. not an error). internal_date is set
 	   if it's non-NULL. */
-	IBuffer *(*open_mail)(MailIndex *index, MailIndexRecord *rec,
+	IStream *(*open_mail)(MailIndex *index, MailIndexRecord *rec,
 			      time_t *internal_date, int *deleted);
 
 	/* Returns internal date of message, or (time_t)-1 if error occured. */
@@ -361,7 +361,7 @@
 
 	char *mbox_path; /* mbox-specific path to the actual mbox file */
 	int mbox_fd;
-	IBuffer *mbox_inbuf;
+	IStream *mbox_stream;
 	MailLockType mbox_lock_type;
 	dev_t mbox_dotlock_dev;
 	ino_t mbox_dotlock_ino;
@@ -470,7 +470,7 @@
 int mail_index_verify_hole_range(MailIndex *index);
 void mail_index_mark_flag_changes(MailIndex *index, MailIndexRecord *rec,
 				  MailFlags old_flags, MailFlags new_flags);
-void mail_index_update_headers(MailIndexUpdate *update, IBuffer *inbuf,
+void mail_index_update_headers(MailIndexUpdate *update, IStream *input,
                                MailDataField cache_fields,
 			       MessageHeaderFunc header_func, void *context);
 int mail_index_update_cache(MailIndex *index);
--- a/src/lib-index/maildir/maildir-index.h	Fri Dec 06 00:37:33 2002 +0200
+++ b/src/lib-index/maildir/maildir-index.h	Fri Dec 06 03:09:22 2002 +0200
@@ -20,7 +20,7 @@
 int maildir_index_build_dir(MailIndex *index, const char *source_dir,
 			    const char *dest_dir);
 
-IBuffer *maildir_open_mail(MailIndex *index, MailIndexRecord *rec,
+IStream *maildir_open_mail(MailIndex *index, MailIndexRecord *rec,
 			   time_t *internal_date, int *deleted);
 
 int maildir_record_update(MailIndex *index, MailIndexUpdate *update, int fd);
--- a/src/lib-index/maildir/maildir-open.c	Fri Dec 06 00:37:33 2002 +0200
+++ b/src/lib-index/maildir/maildir-open.c	Fri Dec 06 03:09:22 2002 +0200
@@ -1,7 +1,7 @@
 /* Copyright (C) 2002 Timo Sirainen */
 
 #include "lib.h"
-#include "ibuffer.h"
+#include "istream.h"
 #include "maildir-index.h"
 #include "mail-index-data.h"
 #include "mail-index-util.h"
@@ -10,7 +10,7 @@
 #include <fcntl.h>
 #include <sys/stat.h>
 
-IBuffer *maildir_open_mail(MailIndex *index, MailIndexRecord *rec,
+IStream *maildir_open_mail(MailIndex *index, MailIndexRecord *rec,
 			   time_t *internal_date, int *deleted)
 {
 	struct stat st;
@@ -54,10 +54,10 @@
 	}
 
 	if (index->mail_read_mmaped) {
-		return i_buffer_create_mmap(fd, default_pool,
+		return i_stream_create_mmap(fd, default_pool,
 					    MAIL_MMAP_BLOCK_SIZE, 0, 0, TRUE);
 	} else {
-		return i_buffer_create_file(fd, default_pool,
+		return i_stream_create_file(fd, default_pool,
 					    MAIL_READ_BLOCK_SIZE, TRUE);
 	}
 }
--- a/src/lib-index/maildir/maildir-update.c	Fri Dec 06 00:37:33 2002 +0200
+++ b/src/lib-index/maildir/maildir-update.c	Fri Dec 06 03:09:22 2002 +0200
@@ -1,12 +1,12 @@
 /* Copyright (C) 2002 Timo Sirainen */
 
 #include "lib.h"
-#include "ibuffer.h"
+#include "istream.h"
 #include "maildir-index.h"
 
 int maildir_record_update(MailIndex *index, MailIndexUpdate *update, int fd)
 {
-	IBuffer *inbuf;
+	IStream *input;
         MailDataField cache_fields;
 
 	/* don't even bother opening the file if we're not going to do
@@ -17,14 +17,14 @@
 
 	t_push();
 	if (index->mail_read_mmaped) {
-		inbuf = i_buffer_create_mmap(fd, data_stack_pool,
+		input = i_stream_create_mmap(fd, data_stack_pool,
 					     MAIL_MMAP_BLOCK_SIZE, 0, 0, FALSE);
 	} else {
-		inbuf = i_buffer_create_file(fd, data_stack_pool,
+		input = i_stream_create_file(fd, data_stack_pool,
 					     MAIL_READ_BLOCK_SIZE, FALSE);
 	}
-	mail_index_update_headers(update, inbuf, cache_fields, NULL, NULL);
-	i_buffer_unref(inbuf);
+	mail_index_update_headers(update, input, cache_fields, NULL, NULL);
+	i_stream_unref(input);
 	t_pop();
 	return TRUE;
 }
--- a/src/lib-index/mbox/mbox-append.c	Fri Dec 06 00:37:33 2002 +0200
+++ b/src/lib-index/mbox/mbox-append.c	Fri Dec 06 03:09:22 2002 +0200
@@ -2,13 +2,13 @@
 
 #include "lib.h"
 #include "ioloop.h"
-#include "ibuffer.h"
+#include "istream.h"
 #include "hex-binary.h"
 #include "md5.h"
 #include "mbox-index.h"
 #include "mail-index-util.h"
 
-static int mbox_index_append_next(MailIndex *index, IBuffer *inbuf)
+static int mbox_index_append_next(MailIndex *index, IStream *input)
 {
 	MailIndexRecord *rec;
 	MailIndexUpdate *update;
@@ -22,7 +22,7 @@
 
 	/* get the From-line */
 	pos = 0;
-	while (i_buffer_read_data(inbuf, &data, &size, pos) > 0) {
+	while (i_stream_read_data(input, &data, &size, pos) > 0) {
 		for (; pos < size; pos++) {
 			if (data[pos] == '\n')
 				break;
@@ -48,13 +48,13 @@
 	if (internal_date == (time_t)-1)
 		internal_date = ioloop_time;
 
-	i_buffer_skip(inbuf, pos+1);
-	abs_start_offset = inbuf->start_offset + inbuf->v_offset;
+	i_stream_skip(input, pos+1);
+	abs_start_offset = input->start_offset + input->v_offset;
 
 	/* now, find the end of header. also stops at "\nFrom " if it's
 	   found (broken messages) */
-	mbox_skip_header(inbuf);
-	eoh_offset = inbuf->v_offset;
+	mbox_skip_header(input);
+	eoh_offset = input->v_offset;
 
 	/* add message to index */
 	rec = index->append_begin(index);
@@ -71,22 +71,22 @@
 				&abs_start_offset, sizeof(uoff_t));
 
 	/* parse the header and cache wanted fields. get the message flags
-	   from Status and X-Status fields. temporarily limit the buffer size
+	   from Status and X-Status fields. temporarily limit the stream length
 	   so the message body is parsed properly.
 
-	   the buffer limit is raised again by mbox_header_func after reading
-	   the headers. it uses Content-Length if available or finds the next
-	   From-line. */
-	mbox_header_init_context(&ctx, index, inbuf);
+	   the stream length limit is raised again by mbox_header_func after
+	   reading the headers. it uses Content-Length if available or finds
+	   the next From-line. */
+	mbox_header_init_context(&ctx, index, input);
         ctx.set_read_limit = TRUE;
 
-	i_buffer_seek(inbuf, abs_start_offset - inbuf->start_offset);
+	i_stream_seek(input, abs_start_offset - input->start_offset);
 
-	i_buffer_set_read_limit(inbuf, eoh_offset);
-	mail_index_update_headers(update, inbuf, 0, mbox_header_func, &ctx);
+	i_stream_set_read_limit(input, eoh_offset);
+	mail_index_update_headers(update, input, 0, mbox_header_func, &ctx);
 
-	i_buffer_seek(inbuf, inbuf->v_limit);
-	i_buffer_set_read_limit(inbuf, 0);
+	i_stream_seek(input, input->v_limit);
+	i_stream_set_read_limit(input, 0);
 
 	/* save MD5 */
 	md5_final(&ctx.md5, md5_digest);
@@ -110,9 +110,9 @@
 	return !failed;
 }
 
-int mbox_index_append(MailIndex *index, IBuffer *inbuf)
+int mbox_index_append(MailIndex *index, IStream *input)
 {
-	if (inbuf->v_offset == inbuf->v_size) {
+	if (input->v_offset == input->v_size) {
 		/* no new data */
 		return TRUE;
 	}
@@ -121,10 +121,10 @@
 		return FALSE;
 
 	for (;;) {
-		if (inbuf->start_offset + inbuf->v_offset != 0) {
+		if (input->start_offset + input->v_offset != 0) {
 			/* we're at the [\r]\n before the From-line,
 			   skip it */
-			if (!mbox_skip_crlf(inbuf)) {
+			if (!mbox_skip_crlf(input)) {
 				index_set_error(index,
 						"Error indexing mbox file %s: "
 						"LF not found where expected",
@@ -135,10 +135,10 @@
 			}
 		}
 
-		if (inbuf->v_offset == inbuf->v_size)
+		if (input->v_offset == input->v_size)
 			break;
 
-		if (!mbox_index_append_next(index, inbuf))
+		if (!mbox_index_append_next(index, input))
 			return FALSE;
 	}
 
--- a/src/lib-index/mbox/mbox-index.c	Fri Dec 06 00:37:33 2002 +0200
+++ b/src/lib-index/mbox/mbox-index.c	Fri Dec 06 03:09:22 2002 +0200
@@ -1,7 +1,7 @@
 /* Copyright (C) 2002 Timo Sirainen */
 
 #include "lib.h"
-#include "ibuffer.h"
+#include "istream.h"
 #include "rfc822-tokenize.h"
 #include "mbox-index.h"
 #include "mbox-lock.h"
@@ -49,7 +49,8 @@
 	return TRUE;
 }
 
-IBuffer *mbox_get_inbuf(MailIndex *index, uoff_t offset, MailLockType lock_type)
+IStream *mbox_get_stream(MailIndex *index, uoff_t offset,
+			 MailLockType lock_type)
 {
 	i_assert(offset < OFF_T_MAX);
 
@@ -70,11 +71,11 @@
 		break;
 	}
 
-	if (index->mbox_inbuf == NULL) {
+	if (index->mbox_stream == NULL) {
 		/* FIXME: breaks expunge */
 		/*if (index->mail_read_mmaped) {*/
-			index->mbox_inbuf =
-				i_buffer_create_mmap(index->mbox_fd,
+			index->mbox_stream =
+				i_stream_create_mmap(index->mbox_fd,
 						     default_pool,
 						     MAIL_MMAP_BLOCK_SIZE,
 						     0, 0, FALSE);
@@ -84,34 +85,34 @@
 				return NULL;
 			}
 
-			index->mbox_inbuf =
-				i_buffer_create_file(index->mbox_fd,
+			index->mbox_stream =
+				i_stream_create_file(index->mbox_fd,
 						     default_pool,
 						     MAIL_READ_BLOCK_SIZE,
 						     FALSE);
 		}*/
 	}
 
-	i_buffer_set_read_limit(index->mbox_inbuf, 0);
-	i_buffer_set_start_offset(index->mbox_inbuf, (uoff_t)offset);
-	i_buffer_seek(index->mbox_inbuf, 0);
+	i_stream_set_read_limit(index->mbox_stream, 0);
+	i_stream_set_start_offset(index->mbox_stream, (uoff_t)offset);
+	i_stream_seek(index->mbox_stream, 0);
 
-	i_buffer_ref(index->mbox_inbuf);
-	return index->mbox_inbuf;
+	i_stream_ref(index->mbox_stream);
+	return index->mbox_stream;
 }
 
-void mbox_file_close_inbuf(MailIndex *index)
+void mbox_file_close_stream(MailIndex *index)
 {
-	if (index->mbox_inbuf != NULL) {
-		i_buffer_close(index->mbox_inbuf);
-		i_buffer_unref(index->mbox_inbuf);
-		index->mbox_inbuf = NULL;
+	if (index->mbox_stream != NULL) {
+		i_stream_close(index->mbox_stream);
+		i_stream_unref(index->mbox_stream);
+		index->mbox_stream = NULL;
 	}
 }
 
 void mbox_file_close_fd(MailIndex *index)
 {
-	mbox_file_close_inbuf(index);
+	mbox_file_close_stream(index);
 
 	if (index->mbox_fd != -1) {
 		close(index->mbox_fd);
@@ -120,13 +121,13 @@
 }
 
 void mbox_header_init_context(MboxHeaderContext *ctx, MailIndex *index,
-			      IBuffer *inbuf)
+			      IStream *input)
 {
 	memset(ctx, 0, sizeof(MboxHeaderContext));
 	md5_init(&ctx->md5);
 
 	ctx->index = index;
-	ctx->inbuf = inbuf;
+	ctx->input = input;
 	ctx->custom_flags = mail_custom_flags_list_get(index->custom_flags);
 }
 
@@ -261,21 +262,21 @@
 			break;
 
 		/* a) use Content-Length, b) search for "From "-line */
-		start_offset = ctx->inbuf->v_offset;
-		i_buffer_set_read_limit(ctx->inbuf, 0);
+		start_offset = ctx->input->v_offset;
+		i_stream_set_read_limit(ctx->input, 0);
 
 		end_offset = start_offset + ctx->content_length;
 		if (ctx->content_length == 0 ||
-		    !mbox_verify_end_of_body(ctx->inbuf, end_offset)) {
+		    !mbox_verify_end_of_body(ctx->input, end_offset)) {
 			if (ctx->content_length != 0)
-				i_buffer_seek(ctx->inbuf, start_offset);
-			mbox_skip_message(ctx->inbuf);
-			end_offset = ctx->inbuf->v_offset;
+				i_stream_seek(ctx->input, start_offset);
+			mbox_skip_message(ctx->input);
+			end_offset = ctx->input->v_offset;
 			ctx->content_length = end_offset - start_offset;
 		}
 
-		i_buffer_seek(ctx->inbuf, start_offset);
-		i_buffer_set_read_limit(ctx->inbuf, end_offset);
+		i_stream_seek(ctx->input, start_offset);
+		i_stream_set_read_limit(ctx->input, end_offset);
 		break;
 
 	case 'R':
@@ -420,16 +421,16 @@
 	}
 }
 
-int mbox_skip_crlf(IBuffer *inbuf)
+int mbox_skip_crlf(IStream *input)
 {
 	const unsigned char *data;
 	size_t size, pos;
 
 	pos = 0;
-	while (i_buffer_read_data(inbuf, &data, &size, pos) > 0) {
+	while (i_stream_read_data(input, &data, &size, pos) > 0) {
 		if (pos == 0) {
 			if (data[0] == '\n') {
-				i_buffer_skip(inbuf, 1);
+				i_stream_skip(input, 1);
 				return TRUE;
 			}
 			if (data[0] != '\r')
@@ -442,7 +443,7 @@
 			if (data[1] != '\n')
 				return FALSE;
 
-			i_buffer_skip(inbuf, 2);
+			i_stream_skip(input, 2);
 			return TRUE;
 		}
 	}
@@ -451,32 +452,32 @@
 	return TRUE;
 }
 
-void mbox_skip_empty_lines(IBuffer *inbuf)
+void mbox_skip_empty_lines(IStream *input)
 {
 	const unsigned char *data;
 	size_t i, size;
 
 	/* skip empty lines at beginning */
-	while (i_buffer_read_data(inbuf, &data, &size, 0) > 0) {
+	while (i_stream_read_data(input, &data, &size, 0) > 0) {
 		for (i = 0; i < size; i++) {
 			if (data[i] != '\r' && data[i] != '\n')
 				break;
 		}
 
-		i_buffer_skip(inbuf, i);
+		i_stream_skip(input, i);
 
 		if (i < size)
 			break;
 	}
 }
 
-static int mbox_is_valid_from(IBuffer *inbuf, size_t startpos)
+static int mbox_is_valid_from(IStream *input, size_t startpos)
 {
 	const unsigned char *msg;
 	size_t i, size;
 
 	i = startpos;
-	while (i_buffer_read_data(inbuf, &msg, &size, i) > 0) {
+	while (i_stream_read_data(input, &msg, &size, i) > 0) {
 		for (; i < size; i++) {
 			if (msg[i] == '\n') {
 				msg += startpos;
@@ -490,7 +491,7 @@
 	return FALSE;
 }
 
-static void mbox_skip_forward(IBuffer *inbuf, int header)
+static void mbox_skip_forward(IStream *input, int header)
 {
 	const unsigned char *msg;
 	size_t i, size, startpos, eoh;
@@ -500,7 +501,7 @@
 	   buffer */
 	startpos = i = 0; eoh = 0; lastmsg = TRUE;
 	state = '\n';
-	while (i_buffer_read_data(inbuf, &msg, &size, startpos) > 0) {
+	while (i_stream_read_data(input, &msg, &size, startpos) > 0) {
 		for (i = startpos; i < size; i++) {
 			new_state = 0;
 			switch (state) {
@@ -544,7 +545,7 @@
 				break;
 			case 'm':
 				if (msg[i] == ' ') {
-					if (mbox_is_valid_from(inbuf, i+1)) {
+					if (mbox_is_valid_from(input, i+1)) {
 						/* Go back "From" */
 						i -= 4;
 
@@ -557,7 +558,7 @@
 						if (i > 0 && msg[i-1] == '\r')
 							i--;
 
-						i_buffer_skip(inbuf, i);
+						i_stream_skip(input, i);
 						return;
 					}
 				}
@@ -570,7 +571,7 @@
 				state = msg[i] == '\n' ? '\n' : 0;
 			else {
 				/* end of header position confirmed */
-				i_buffer_skip(inbuf, eoh);
+				i_stream_skip(input, eoh);
 				return;
 			}
 		}
@@ -585,20 +586,20 @@
 			eoh -= i;
 		}
 
-		i_buffer_skip(inbuf, i);
+		i_stream_skip(input, i);
 	}
 
 	if (eoh != 0) {
 		/* make sure we didn't end with \n\n or \n\r\n. In these
 		   cases the last [\r]\n doesn't belong to our message. */
 		if (eoh < size && (msg[eoh] != '\r' || eoh < size-1)) {
-			i_buffer_skip(inbuf, eoh);
+			i_stream_skip(input, eoh);
 			return;
 		}
 	}
 
 	/* end of file, leave the last [\r]\n */
-	msg = i_buffer_get_data(inbuf, &size);
+	msg = i_stream_get_data(input, &size);
 	if (size == startpos && startpos > 0) {
 		if (msg[startpos-1] == '\n')
 			startpos--;
@@ -606,39 +607,39 @@
 			startpos--;
 	}
 
-	i_buffer_skip(inbuf, startpos);
+	i_stream_skip(input, startpos);
 }
 
-void mbox_skip_header(IBuffer *inbuf)
+void mbox_skip_header(IStream *input)
 {
-	mbox_skip_forward(inbuf, TRUE);
+	mbox_skip_forward(input, TRUE);
 }
 
-void mbox_skip_message(IBuffer *inbuf)
+void mbox_skip_message(IStream *input)
 {
-	mbox_skip_forward(inbuf, FALSE);
+	mbox_skip_forward(input, FALSE);
 }
 
-int mbox_verify_end_of_body(IBuffer *inbuf, uoff_t end_offset)
+int mbox_verify_end_of_body(IStream *input, uoff_t end_offset)
 {
 	const unsigned char *data;
 	size_t size;
 
-	if (end_offset > inbuf->v_size) {
+	if (end_offset > input->v_size) {
 		/* missing data */
 		return FALSE;
 	}
 
-	i_buffer_seek(inbuf, end_offset);
+	i_stream_seek(input, end_offset);
 
-	if (inbuf->v_offset == inbuf->v_size) {
+	if (input->v_offset == input->v_size) {
 		/* end of file. a bit unexpected though,
 		   since \n is missing. */
 		return TRUE;
 	}
 
 	/* read forward a bit */
-	if (i_buffer_read_data(inbuf, &data, &size, 6) < 0)
+	if (i_stream_read_data(input, &data, &size, 6) < 0)
 		return FALSE;
 
 	/* either there should be the next From-line,
--- a/src/lib-index/mbox/mbox-index.h	Fri Dec 06 00:37:33 2002 +0200
+++ b/src/lib-index/mbox/mbox-index.h	Fri Dec 06 03:09:22 2002 +0200
@@ -11,7 +11,7 @@
 	MD5Context md5;
 	int received;
 
-	IBuffer *inbuf;
+	IStream *input;
 	uoff_t content_length;
 	int set_read_limit;
 } MboxHeaderContext;
@@ -22,13 +22,13 @@
    which is useful when you want to be sure you're not accessing a deleted
    mbox file. */
 int mbox_file_open(MailIndex *index);
-IBuffer *mbox_get_inbuf(MailIndex *index, uoff_t offset,
-			MailLockType lock_type);
-void mbox_file_close_inbuf(MailIndex *index);
+IStream *mbox_get_stream(MailIndex *index, uoff_t offset,
+			 MailLockType lock_type);
+void mbox_file_close_stream(MailIndex *index);
 void mbox_file_close_fd(MailIndex *index);
 
 void mbox_header_init_context(MboxHeaderContext *ctx, MailIndex *index,
-			      IBuffer *inbuf);
+			      IStream *input);
 void mbox_header_free_context(MboxHeaderContext *ctx);
 void mbox_header_func(MessagePart *part __attr_unused__,
 		      const char *name, size_t name_len,
@@ -38,11 +38,11 @@
 			 const char *custom_flags[MAIL_CUSTOM_FLAGS_COUNT],
 			 void (*func)(const char *, size_t, int, void *),
 			 void *context);
-int mbox_skip_crlf(IBuffer *inbuf);
-void mbox_skip_empty_lines(IBuffer *inbuf);
-void mbox_skip_header(IBuffer *inbuf);
-void mbox_skip_message(IBuffer *inbuf);
-int mbox_verify_end_of_body(IBuffer *inbuf, uoff_t end_offset);
+int mbox_skip_crlf(IStream *input);
+void mbox_skip_empty_lines(IStream *input);
+void mbox_skip_header(IStream *input);
+void mbox_skip_message(IStream *input);
+int mbox_verify_end_of_body(IStream *input, uoff_t end_offset);
 int mbox_mail_get_location(MailIndex *index, MailIndexRecord *rec,
 			   uoff_t *offset, uoff_t *hdr_size, uoff_t *body_size);
 
@@ -50,10 +50,10 @@
 int mbox_index_rebuild(MailIndex *index);
 int mbox_index_sync(MailIndex *index, MailLockType lock_type, int *changes);
 int mbox_sync_full(MailIndex *index);
-IBuffer *mbox_open_mail(MailIndex *index, MailIndexRecord *rec,
+IStream *mbox_open_mail(MailIndex *index, MailIndexRecord *rec,
 			time_t *internal_date, int *deleted);
 
-int mbox_index_append(MailIndex *index, IBuffer *inbuf);
+int mbox_index_append(MailIndex *index, IStream *input);
 
 time_t mbox_from_parse_date(const char *msg, size_t size);
 const char *mbox_from_create(const char *sender, time_t time);
--- a/src/lib-index/mbox/mbox-lock.c	Fri Dec 06 00:37:33 2002 +0200
+++ b/src/lib-index/mbox/mbox-lock.c	Fri Dec 06 03:09:22 2002 +0200
@@ -390,7 +390,7 @@
 	   been changes to file size which would break things. or actually
 	   it'd break only if file was shrinked+grown back to exact size,
 	   but still possible :) */
-	mbox_file_close_inbuf(index);
+	mbox_file_close_stream(index);
 
 	index->mbox_lock_type = MAIL_LOCK_UNLOCK;
 	return !failed;
--- a/src/lib-index/mbox/mbox-open.c	Fri Dec 06 00:37:33 2002 +0200
+++ b/src/lib-index/mbox/mbox-open.c	Fri Dec 06 03:09:22 2002 +0200
@@ -1,7 +1,7 @@
 /* Copyright (C) 2002 Timo Sirainen */
 
 #include "lib.h"
-#include "ibuffer.h"
+#include "istream.h"
 #include "mbox-index.h"
 #include "mail-index-data.h"
 #include "mail-index-util.h"
@@ -10,10 +10,10 @@
 #include <unistd.h>
 #include <fcntl.h>
 
-IBuffer *mbox_open_mail(MailIndex *index, MailIndexRecord *rec,
+IStream *mbox_open_mail(MailIndex *index, MailIndexRecord *rec,
 			time_t *internal_date, int *deleted)
 {
-	IBuffer *inbuf;
+	IStream *input;
 	uoff_t offset, hdr_size, body_size;
 
 	i_assert(index->lock_type != MAIL_LOCK_UNLOCK);
@@ -27,8 +27,8 @@
 	if (!mbox_mail_get_location(index, rec, &offset, &hdr_size, &body_size))
 		return NULL;
 
-	inbuf = mbox_get_inbuf(index, offset, MAIL_LOCK_SHARED);
-	if (inbuf == NULL)
+	input = mbox_get_stream(index, offset, MAIL_LOCK_SHARED);
+	if (input == NULL)
 		return NULL;
 
 	if (internal_date != NULL)
@@ -36,6 +36,6 @@
 
 	i_assert(index->mbox_sync_counter == index->mbox_lock_counter);
 
-	i_buffer_set_read_limit(inbuf, hdr_size + body_size);
-	return inbuf;
+	i_stream_set_read_limit(input, hdr_size + body_size);
+	return input;
 }
--- a/src/lib-index/mbox/mbox-rebuild.c	Fri Dec 06 00:37:33 2002 +0200
+++ b/src/lib-index/mbox/mbox-rebuild.c	Fri Dec 06 03:09:22 2002 +0200
@@ -1,7 +1,7 @@
 /* Copyright (C) 2002 Timo Sirainen */
 
 #include "lib.h"
-#include "ibuffer.h"
+#include "istream.h"
 #include "mbox-index.h"
 #include "mbox-lock.h"
 #include "mail-index-data.h"
@@ -14,7 +14,7 @@
 
 int mbox_index_rebuild(MailIndex *index)
 {
-	IBuffer *inbuf;
+	IStream *input;
 	struct stat st;
 	int failed;
 
@@ -43,14 +43,14 @@
 	if (!mail_index_data_reset(index->data))
 		return FALSE;
 
-	inbuf = mbox_get_inbuf(index, 0, MAIL_LOCK_SHARED);
-	if (inbuf == NULL)
+	input = mbox_get_stream(index, 0, MAIL_LOCK_SHARED);
+	if (input == NULL)
 		return FALSE;
 
-	mbox_skip_empty_lines(inbuf);
-	failed = !mbox_index_append(index, inbuf);
+	mbox_skip_empty_lines(input);
+	failed = !mbox_index_append(index, input);
 
-	i_buffer_unref(inbuf);
+	i_stream_unref(input);
 
 	if (failed)
 		return FALSE;
--- a/src/lib-index/mbox/mbox-rewrite.c	Fri Dec 06 00:37:33 2002 +0200
+++ b/src/lib-index/mbox/mbox-rewrite.c	Fri Dec 06 03:09:22 2002 +0200
@@ -1,8 +1,8 @@
 /* Copyright (C) 2002 Timo Sirainen */
 
 #include "lib.h"
-#include "ibuffer.h"
-#include "obuffer.h"
+#include "istream.h"
+#include "ostream.h"
 #include "temp-string.h"
 #include "write-full.h"
 #include "mbox-index.h"
@@ -16,7 +16,7 @@
 #include <fcntl.h>
 
 typedef struct {
-	OBuffer *outbuf;
+	OStream *output;
 	int failed;
 
 	uoff_t content_length;
@@ -49,21 +49,22 @@
 				  MAIL_INDEX_FLAG_DIRTY_CUSTOMFLAGS);
 }
 
-static int mbox_write(MailIndex *index, IBuffer *inbuf, OBuffer *outbuf,
+static int mbox_write(MailIndex *index, IStream *input, OStream *output,
 		      uoff_t end_offset)
 {
 	uoff_t old_limit;
 	int failed;
 
-	i_assert(inbuf->v_offset <= end_offset);
+	i_assert(input->v_offset <= end_offset);
 
-	old_limit = inbuf->v_limit;
-	i_buffer_set_read_limit(inbuf, end_offset);
-	if (o_buffer_send_ibuffer(outbuf, inbuf) < 0) {
+	old_limit = input->v_limit;
+	i_stream_set_read_limit(input, end_offset);
+	if (o_stream_send_istream(output, input) < 0) {
 		index_set_error(index, "Error rewriting mbox file %s: %s",
-				index->mbox_path, strerror(outbuf->buf_errno));
+				index->mbox_path,
+				strerror(output->stream_errno));
 		failed = TRUE;
-	} else if (inbuf->v_offset < end_offset) {
+	} else if (input->v_offset < end_offset) {
 		/* fsck should have noticed it.. */
 		index_set_error(index, "Error rewriting mbox file %s: "
 				"Unexpected end of file", index->mbox_path);
@@ -72,7 +73,7 @@
 		failed = FALSE;
 	}
 
-	i_buffer_set_read_limit(inbuf, old_limit);
+	i_stream_set_read_limit(input, old_limit);
 	return !failed;
 }
 
@@ -83,21 +84,21 @@
 
 	str = t_strdup_printf("X-IMAPbase: %u %u",
 			      ctx->uid_validity, ctx->uid_last);
-	if (o_buffer_send(ctx->outbuf, str, strlen(str)) < 0)
+	if (o_stream_send(ctx->output, str, strlen(str)) < 0)
 		return FALSE;
 
 	for (i = 0; i < MAIL_CUSTOM_FLAGS_COUNT; i++) {
 		if (ctx->custom_flags[i] != NULL) {
-			if (o_buffer_send(ctx->outbuf, " ", 1) < 0)
+			if (o_stream_send(ctx->output, " ", 1) < 0)
 				return FALSE;
 
-			if (o_buffer_send(ctx->outbuf, ctx->custom_flags[i],
+			if (o_stream_send(ctx->output, ctx->custom_flags[i],
 					  strlen(ctx->custom_flags[i])) < 0)
 				return FALSE;
 		}
 	}
 
-	if (o_buffer_send(ctx->outbuf, "\n", 1) < 0)
+	if (o_stream_send(ctx->output, "\n", 1) < 0)
 		return FALSE;
 
 	return TRUE;
@@ -112,16 +113,16 @@
 	    x_keywords == NULL)
 		return TRUE;
 
-	if (o_buffer_send(ctx->outbuf, "X-Keywords:", 11) < 0)
+	if (o_stream_send(ctx->output, "X-Keywords:", 11) < 0)
 		return FALSE;
 
 	field = 1 << MAIL_CUSTOM_FLAG_1_BIT;
 	for (i = 0; i < MAIL_CUSTOM_FLAGS_COUNT; i++, field <<= 1) {
 		if ((ctx->msg_flags & field) && ctx->custom_flags[i] != NULL) {
-			if (o_buffer_send(ctx->outbuf, " ", 1) < 0)
+			if (o_stream_send(ctx->output, " ", 1) < 0)
 				return FALSE;
 
-			if (o_buffer_send(ctx->outbuf, ctx->custom_flags[i],
+			if (o_stream_send(ctx->output, ctx->custom_flags[i],
 					  strlen(ctx->custom_flags[i])) < 0)
 				return FALSE;
 		}
@@ -129,15 +130,15 @@
 
 	if (x_keywords != NULL) {
 		/* X-Keywords that aren't custom flags */
-		if (o_buffer_send(ctx->outbuf, " ", 1) < 0)
+		if (o_stream_send(ctx->output, " ", 1) < 0)
 			return FALSE;
 
-		if (o_buffer_send(ctx->outbuf, x_keywords,
+		if (o_stream_send(ctx->output, x_keywords,
 				  strlen(x_keywords)) < 0)
 			return FALSE;
 	}
 
-	if (o_buffer_send(ctx->outbuf, "\n", 1) < 0)
+	if (o_stream_send(ctx->output, "\n", 1) < 0)
 		return FALSE;
 
 	return TRUE;
@@ -151,9 +152,9 @@
 	if (status != NULL)
 		str = t_strconcat(str, status, NULL);
 
-	if (o_buffer_send(ctx->outbuf, str, strlen(str)) < 0)
+	if (o_stream_send(ctx->output, str, strlen(str)) < 0)
 		return FALSE;
-	if (o_buffer_send(ctx->outbuf, "\n", 1) < 0)
+	if (o_stream_send(ctx->output, "\n", 1) < 0)
 		return FALSE;
 
 	return TRUE;
@@ -175,9 +176,9 @@
 			  (ctx->msg_flags & MAIL_DELETED) ? "T" : "",
 			  x_status, NULL);
 
-	if (o_buffer_send(ctx->outbuf, str, strlen(str)) < 0)
+	if (o_stream_send(ctx->output, str, strlen(str)) < 0)
 		return FALSE;
-	if (o_buffer_send(ctx->outbuf, "\n", 1) < 0)
+	if (o_stream_send(ctx->output, "\n", 1) < 0)
 		return FALSE;
 
 	return TRUE;
@@ -190,7 +191,7 @@
 	i_snprintf(str, sizeof(str), "Content-Length: %"PRIuUOFF_T"\n",
 		   ctx->content_length);
 
-	if (o_buffer_send(ctx->outbuf, str, strlen(str)) < 0)
+	if (o_stream_send(ctx->output, str, strlen(str)) < 0)
 		return FALSE;
 	return TRUE;
 }
@@ -283,19 +284,19 @@
 		(void)mbox_write_content_length(ctx);
 	} else if (name_len > 0) {
 		/* save this header */
-		(void)o_buffer_send(ctx->outbuf, name, name_len);
-		(void)o_buffer_send(ctx->outbuf, ": ", 2);
-		(void)o_buffer_send(ctx->outbuf, value, value_len);
-		(void)o_buffer_send(ctx->outbuf, "\n", 1);
+		(void)o_stream_send(ctx->output, name, name_len);
+		(void)o_stream_send(ctx->output, ": ", 2);
+		(void)o_stream_send(ctx->output, value, value_len);
+		(void)o_stream_send(ctx->output, "\n", 1);
 	}
 
-	if (ctx->outbuf->closed)
+	if (ctx->output->closed)
 		ctx->failed = TRUE;
 }
 
 static int mbox_write_header(MailIndex *index,
 			     MailIndexRecord *rec, unsigned int seq,
-			     IBuffer *inbuf, OBuffer *outbuf, uoff_t end_offset,
+			     IStream *input, OStream *output, uoff_t end_offset,
 			     uoff_t hdr_size, uoff_t body_size)
 {
 	/* We need to update fields that define message flags. Standard fields
@@ -312,7 +313,7 @@
 	MboxRewriteContext ctx;
 	MessageSize hdr_parsed_size;
 
-	if (inbuf->v_offset >= end_offset) {
+	if (input->v_offset >= end_offset) {
 		/* fsck should have noticed it.. */
 		index_set_error(index, "Error rewriting mbox file %s: "
 				"Unexpected end of file", index->mbox_path);
@@ -323,16 +324,16 @@
 
 	/* parse the header, write the fields we don't want to change */
 	memset(&ctx, 0, sizeof(ctx));
-	ctx.outbuf = outbuf;
+	ctx.output = output;
 	ctx.seq = seq;
 	ctx.content_length = body_size;
 	ctx.msg_flags = rec->msg_flags;
 	ctx.uid_validity = index->header->uid_validity-1;
 	ctx.custom_flags = mail_custom_flags_list_get(index->custom_flags);
 
-	i_buffer_set_read_limit(inbuf, inbuf->v_offset + hdr_size);
-	message_parse_header(NULL, inbuf, &hdr_parsed_size, header_func, &ctx);
-	i_buffer_set_read_limit(inbuf, 0);
+	i_stream_set_read_limit(input, input->v_offset + hdr_size);
+	message_parse_header(NULL, input, &hdr_parsed_size, header_func, &ctx);
+	i_stream_set_read_limit(input, 0);
 
 	i_assert(hdr_parsed_size.physical_size == hdr_size);
 
@@ -354,15 +355,15 @@
 	t_pop();
 
 	/* empty line ends headers */
-	(void)o_buffer_send(outbuf, "\n", 1);
+	(void)o_stream_send(output, "\n", 1);
 
 	return TRUE;
 }
 
 static int fd_copy(int in_fd, int out_fd, uoff_t out_offset)
 {
-	IBuffer *inbuf;
-	OBuffer *outbuf;
+	IStream *input;
+	OStream *output;
 	int ret;
 
 	i_assert(out_offset <= OFF_T_MAX);
@@ -372,22 +373,22 @@
 
 	t_push();
 
-	inbuf = i_buffer_create_mmap(in_fd, data_stack_pool,
+	input = i_stream_create_mmap(in_fd, data_stack_pool,
 				     1024*256, 0, 0, FALSE);
-	outbuf = o_buffer_create_file(out_fd, data_stack_pool, 1024, 0, FALSE);
-	o_buffer_set_blocking(outbuf, 60000, NULL, NULL);
+	output = o_stream_create_file(out_fd, data_stack_pool, 1024, 0, FALSE);
+	o_stream_set_blocking(output, 60000, NULL, NULL);
 
-	ret = o_buffer_send_ibuffer(outbuf, inbuf);
+	ret = o_stream_send_istream(output, input);
 	if (ret < 0)
-		errno = outbuf->buf_errno;
+		errno = output->stream_errno;
 	else {
 		/* we may have shrinked the file */
-		i_assert(out_offset + inbuf->v_size <= OFF_T_MAX);
-		ret = ftruncate(out_fd, (off_t) (out_offset + inbuf->v_size));
+		i_assert(out_offset + input->v_size <= OFF_T_MAX);
+		ret = ftruncate(out_fd, (off_t) (out_offset + input->v_size));
 	}
 
-	o_buffer_unref(outbuf);
-	i_buffer_unref(inbuf);
+	o_stream_unref(output);
+	i_stream_unref(input);
 	t_pop();
 
 	return ret;
@@ -403,8 +404,8 @@
 	   interrupted (see below). This rewriting relies quite a lot on
 	   valid header/body sizes which fsck() should have ensured. */
 	MailIndexRecord *rec;
-	IBuffer *inbuf;
-	OBuffer *outbuf;
+	IStream *input;
+	OStream *output;
 	uoff_t offset, hdr_size, body_size, dirty_offset;
 	const char *path;
 	unsigned int seq;
@@ -426,7 +427,7 @@
 		return TRUE;
 	}
 
-	tmp_fd = -1; inbuf = NULL;
+	tmp_fd = -1; input = NULL;
 	failed = TRUE; rewrite = FALSE;
 	do {
 		if (!index->set_lock(index, MAIL_LOCK_EXCLUSIVE))
@@ -435,8 +436,8 @@
 		if (!index->sync_and_lock(index, MAIL_LOCK_EXCLUSIVE, NULL))
 			break;
 
-		inbuf = mbox_get_inbuf(index, 0, MAIL_LOCK_EXCLUSIVE);
-		if (inbuf == NULL)
+		input = mbox_get_stream(index, 0, MAIL_LOCK_EXCLUSIVE);
+		if (input == NULL)
 			break;
 
 		if ((index->header->flags & INDEX_DIRTY_FLAGS) == 0) {
@@ -456,8 +457,8 @@
 	if (!rewrite) {
 		if (!index->set_lock(index, MAIL_LOCK_UNLOCK))
 			failed = TRUE;
-		if (inbuf != NULL)
-			i_buffer_unref(inbuf);
+		if (input != NULL)
+			i_stream_unref(input);
 		return !failed;
 	}
 
@@ -469,10 +470,10 @@
 	}
 	dirty_offset = 0;
 
-	/* note: we can't use data_stack_pool with outbuf because it's
+	/* note: we can't use data_stack_pool with output stream because it's
 	   being written to inside t_push() .. t_pop() calls */
-	outbuf = o_buffer_create_file(tmp_fd, system_pool, 8192, 0, FALSE);
-	o_buffer_set_blocking(outbuf, 60000, NULL, NULL);
+	output = o_stream_create_file(tmp_fd, system_pool, 8192, 0, FALSE);
+	o_stream_set_blocking(output, 60000, NULL, NULL);
 
 	failed = FALSE; seq = 1;
 	rec = index->lookup(index, 1);
@@ -486,14 +487,14 @@
 				break;
 			}
 
-			if (offset < inbuf->v_offset) {
+			if (offset < input->v_offset) {
 				index_set_corrupted(index,
 						    "Invalid message offset");
 				failed = TRUE;
 				break;
 			}
 
-			if (offset + hdr_size + body_size > inbuf->v_size) {
+			if (offset + hdr_size + body_size > input->v_size) {
 				index_set_corrupted(index,
 						    "Invalid message size");
 				failed = TRUE;
@@ -507,19 +508,19 @@
 			dirty_found = TRUE;
 			dirty_offset = offset;
 
-			i_buffer_seek(inbuf, dirty_offset);
+			i_stream_seek(input, dirty_offset);
 		}
 
 		if (dirty_found) {
 			/* write the From-line */
-			if (!mbox_write(index, inbuf, outbuf, offset)) {
+			if (!mbox_write(index, input, output, offset)) {
 				failed = TRUE;
 				break;
 			}
 
 			/* write header, updating flag fields */
 			offset += hdr_size;
-			if (!mbox_write_header(index, rec, seq, inbuf, outbuf,
+			if (!mbox_write_header(index, rec, seq, input, output,
 					       offset, hdr_size, body_size)) {
 				failed = TRUE;
 				break;
@@ -527,7 +528,7 @@
 
 			/* write body */
 			offset += body_size;
-			if (!mbox_write(index, inbuf, outbuf, offset)) {
+			if (!mbox_write(index, input, output, offset)) {
 				failed = TRUE;
 				break;
 			}
@@ -545,17 +546,17 @@
 
 	if (!failed) {
 		/* always end with a \n */
-		(void)o_buffer_send(outbuf, "\n", 1);
+		(void)o_stream_send(output, "\n", 1);
 	}
 
-	if (outbuf->closed) {
-		errno = outbuf->buf_errno;
+	if (output->closed) {
+		errno = output->stream_errno;
 		mbox_set_syscall_error(index, "write()");
 		failed = TRUE;
 	}
 
-	i_buffer_unref(inbuf);
-	o_buffer_unref(outbuf);
+	i_stream_unref(input);
+	o_stream_unref(output);
 
 	if (!failed) {
 		/* POSSIBLE DATA LOSS HERE. We're writing to the mbox file,
--- a/src/lib-index/mbox/mbox-sync-full.c	Fri Dec 06 00:37:33 2002 +0200
+++ b/src/lib-index/mbox/mbox-sync-full.c	Fri Dec 06 03:09:22 2002 +0200
@@ -1,7 +1,7 @@
 /* Copyright (C) 2002 Timo Sirainen */
 
 #include "lib.h"
-#include "ibuffer.h"
+#include "istream.h"
 #include "hex-binary.h"
 #include "message-parser.h"
 #include "message-part-serialize.h"
@@ -12,20 +12,20 @@
 #include <unistd.h>
 #include <fcntl.h>
 
-static void skip_line(IBuffer *inbuf)
+static void skip_line(IStream *input)
 {
 	const unsigned char *msg;
 	size_t i, size;
 
-	while (i_buffer_read_data(inbuf, &msg, &size, 0) > 0) {
+	while (i_stream_read_data(input, &msg, &size, 0) > 0) {
 		for (i = 0; i < size; i++) {
 			if (msg[i] == '\n') {
-				i_buffer_skip(inbuf, i+1);
+				i_stream_skip(input, i+1);
 				return;
 			}
 		}
 
-		i_buffer_skip(inbuf, i);
+		i_stream_skip(input, i);
 	}
 }
 
@@ -90,7 +90,7 @@
 }
 
 static int match_next_record(MailIndex *index, MailIndexRecord *rec,
-			     unsigned int seq, IBuffer *inbuf,
+			     unsigned int seq, IStream *input,
 			     MailIndexRecord **next_rec, int *dirty)
 {
         MailIndexUpdate *update;
@@ -102,8 +102,8 @@
 	*next_rec = NULL;
 
 	/* skip the From-line */
-	skip_line(inbuf);
-	header_offset = inbuf->v_offset;
+	skip_line(input);
+	header_offset = input->v_offset;
 
 	if (!mbox_mail_get_location(index, rec, NULL, &hdr_size, &body_size))
 		return FALSE;
@@ -111,25 +111,25 @@
 	if (body_size == 0) {
 		/* possibly broken message, find the next From-line and make
 		   sure header parser won't pass it. */
-		mbox_skip_header(inbuf);
-		i_buffer_set_read_limit(inbuf, inbuf->v_offset);
-		i_buffer_seek(inbuf, header_offset);
+		mbox_skip_header(input);
+		i_stream_set_read_limit(input, input->v_offset);
+		i_stream_seek(input, header_offset);
 	}
 
 	/* get the MD5 sum of fixed headers and the current message flags
 	   in Status and X-Status fields */
-        mbox_header_init_context(&ctx, index, inbuf);
-	message_parse_header(NULL, inbuf, &hdr_parsed_size,
+        mbox_header_init_context(&ctx, index, input);
+	message_parse_header(NULL, input, &hdr_parsed_size,
 			     mbox_header_func, &ctx);
 	md5_final(&ctx.md5, current_digest);
 
 	mbox_header_free_context(&ctx);
-	i_buffer_set_read_limit(inbuf, 0);
+	i_stream_set_read_limit(input, 0);
 
-	body_offset = inbuf->v_offset;
+	body_offset = input->v_offset;
 	do {
 		if (verify_header_md5sum(index, rec, current_digest) &&
-		    mbox_verify_end_of_body(inbuf, body_offset + body_size)) {
+		    mbox_verify_end_of_body(input, body_offset + body_size)) {
 			/* valid message */
 			update = index->update_begin(index, rec);
 
@@ -179,7 +179,7 @@
 	return TRUE;
 }
 
-static int mbox_sync_buf(MailIndex *index, IBuffer *inbuf)
+static int mbox_sync_from_stream(MailIndex *index, IStream *input)
 {
 	MailIndexRecord *rec;
 	uoff_t from_offset;
@@ -188,11 +188,11 @@
 	unsigned int seq;
 	int dirty;
 
-	mbox_skip_empty_lines(inbuf);
+	mbox_skip_empty_lines(input);
 
 	/* first make sure we start with a "From " line. If file is too
 	   small, we'll just treat it as empty mbox file. */
-	if (i_buffer_read_data(inbuf, &data, &size, 5) > 0 &&
+	if (i_stream_read_data(input, &data, &size, 5) > 0 &&
 	    strncmp((const char *) data, "From ", 5) != 0) {
 		index_set_error(index, "File isn't in mbox format: %s",
 				index->mbox_path);
@@ -212,11 +212,11 @@
 
 	dirty = FALSE;
 	while (rec != NULL) {
-		from_offset = inbuf->v_offset;
-		if (inbuf->v_offset != 0) {
+		from_offset = input->v_offset;
+		if (input->v_offset != 0) {
 			/* we're at the [\r]\n before the From-line,
 			   skip it */
-			if (!mbox_skip_crlf(inbuf)) {
+			if (!mbox_skip_crlf(input)) {
 				/* they just went and broke it, even while
 				   we had it locked. */
 				index_set_error(index,
@@ -227,15 +227,15 @@
 			}
 		}
 
-		if (inbuf->v_offset == inbuf->v_size)
+		if (input->v_offset == input->v_size)
 			break;
 
-		if (!match_next_record(index, rec, seq, inbuf, &rec, &dirty))
+		if (!match_next_record(index, rec, seq, input, &rec, &dirty))
 			return FALSE;
 
 		if (rec == NULL) {
 			/* Get back to line before From */
-			i_buffer_seek(inbuf, from_offset);
+			i_stream_seek(input, from_offset);
 			break;
 		}
 
@@ -255,25 +255,25 @@
 		index->header->flags &= ~MAIL_INDEX_FLAG_DIRTY_MESSAGES;
 	}
 
-	if (inbuf->v_offset == inbuf->v_size)
+	if (input->v_offset == input->v_size)
 		return TRUE;
 	else
-		return mbox_index_append(index, inbuf);
+		return mbox_index_append(index, input);
 }
 
 int mbox_sync_full(MailIndex *index)
 {
-	IBuffer *inbuf;
+	IStream *input;
 	int failed;
 
 	i_assert(index->lock_type == MAIL_LOCK_EXCLUSIVE);
 
-	inbuf = mbox_get_inbuf(index, 0, MAIL_LOCK_SHARED);
-	if (inbuf == NULL)
+	input = mbox_get_stream(index, 0, MAIL_LOCK_SHARED);
+	if (input == NULL)
 		return FALSE;
 
-	failed = !mbox_sync_buf(index, inbuf);
-	i_buffer_unref(inbuf);
+	failed = !mbox_sync_from_stream(index, input);
+	i_stream_unref(input);
 
 	return !failed;
 }
--- a/src/lib-index/mbox/mbox-sync.c	Fri Dec 06 00:37:33 2002 +0200
+++ b/src/lib-index/mbox/mbox-sync.c	Fri Dec 06 03:09:22 2002 +0200
@@ -119,7 +119,7 @@
 	}
 
 	if (index_mtime != st.st_mtime || index->mbox_size != filesize) {
-		mbox_file_close_inbuf(index);
+		mbox_file_close_stream(index);
 
 		index->mbox_size = get_indexed_mbox_size(index);
 		if (index->file_sync_stamp == 0 &&
--- a/src/lib-mail/message-body-search.c	Fri Dec 06 00:37:33 2002 +0200
+++ b/src/lib-mail/message-body-search.c	Fri Dec 06 03:09:22 2002 +0200
@@ -2,7 +2,7 @@
 
 #include "lib.h"
 #include "base64.h"
-#include "ibuffer.h"
+#include "istream.h"
 #include "charset-utf8.h"
 #include "rfc822-tokenize.h"
 #include "quoted-printable.h"
@@ -134,7 +134,7 @@
 	}
 }
 
-static int message_search_header(PartSearchContext *ctx, IBuffer *inbuf)
+static int message_search_header(PartSearchContext *ctx, IStream *input)
 {
 	ctx->hdr_search_ctx = message_header_search_init(data_stack_pool,
 							 ctx->body_ctx->key,
@@ -143,7 +143,7 @@
 
 	/* we default to text content-type */
 	ctx->content_type_text = TRUE;
-	message_parse_header(NULL, inbuf, NULL, header_find, ctx);
+	message_parse_header(NULL, input, NULL, header_find, ctx);
 
 	return ctx->found;
 }
@@ -252,7 +252,7 @@
 	return 0;
 }
 
-static int message_search_body(PartSearchContext *ctx, IBuffer *inbuf,
+static int message_search_body(PartSearchContext *ctx, IStream *input,
 			       MessagePart *part)
 {
 	const unsigned char *data, *decoded;
@@ -280,15 +280,15 @@
 	ctx->match_count = 0;
 	ctx->matches = t_malloc(sizeof(size_t) * ctx->body_ctx->key_len);
 
-	i_buffer_skip(inbuf, part->physical_pos +
-		      part->header_size.physical_size - inbuf->v_offset);
+	i_stream_skip(input, part->physical_pos +
+		      part->header_size.physical_size - input->v_offset);
 
-	old_limit = inbuf->v_limit;
-	i_buffer_set_read_limit(inbuf, inbuf->v_offset +
+	old_limit = input->v_limit;
+	i_stream_set_read_limit(input, input->v_offset +
 				part->body_size.physical_size);
 
 	found = FALSE; pos = 0;
-	while (i_buffer_read_data(inbuf, &data, &data_size, pos) > 0) {
+	while (i_stream_read_data(input, &data, &data_size, pos) > 0) {
 		/* limit the size of t_malloc()s */
 		if (data_size > DECODE_BLOCK_SIZE)
 			data_size = DECODE_BLOCK_SIZE;
@@ -318,11 +318,11 @@
 		}
 
 		t_pop();
-		i_buffer_skip(inbuf, data_size);
+		i_stream_skip(input, data_size);
 		pos -= data_size;
 	}
 
-	i_buffer_set_read_limit(inbuf, old_limit);
+	i_stream_set_read_limit(input, old_limit);
 
 	if (ctx->translation != NULL)
 		charset_to_utf8_end(ctx->translation);
@@ -355,7 +355,7 @@
 	return TRUE;
 }
 
-static int message_body_search_ctx(BodySearchContext *ctx, IBuffer *inbuf,
+static int message_body_search_ctx(BodySearchContext *ctx, IStream *input,
 				   MessagePart *part)
 {
 	PartSearchContext part_ctx;
@@ -363,9 +363,9 @@
 
 	found = FALSE;
 	while (part != NULL && !found) {
-		i_assert(inbuf->v_offset <= part->physical_pos);
+		i_assert(input->v_offset <= part->physical_pos);
 
-		i_buffer_skip(inbuf, part->physical_pos - inbuf->v_offset);
+		i_stream_skip(input, part->physical_pos - input->v_offset);
 
 		memset(&part_ctx, 0, sizeof(part_ctx));
 		part_ctx.body_ctx = ctx;
@@ -374,14 +374,14 @@
 
 		t_push();
 
-		if (message_search_header(&part_ctx, inbuf)) {
+		if (message_search_header(&part_ctx, input)) {
 			found = TRUE;
 		} else if (part->children != NULL) {
 			/* multipart/xxx or message/rfc822 */
-			if (message_body_search_ctx(ctx, inbuf, part->children))
+			if (message_body_search_ctx(ctx, input, part->children))
 				found = TRUE;
 		} else {
-			if (message_search_body(&part_ctx, inbuf, part))
+			if (message_search_body(&part_ctx, input, part))
 				found = TRUE;
 		}
 
@@ -394,7 +394,7 @@
 }
 
 int message_body_search(const char *key, const char *charset,
-			int *unknown_charset, IBuffer *inbuf,
+			int *unknown_charset, IStream *input,
 			MessagePart *part, int search_header)
 {
         BodySearchContext ctx;
@@ -403,5 +403,5 @@
 				      search_header))
 		return -1;
 
-	return message_body_search_ctx(&ctx, inbuf, part);
+	return message_body_search_ctx(&ctx, input, part);
 }
--- a/src/lib-mail/message-body-search.h	Fri Dec 06 00:37:33 2002 +0200
+++ b/src/lib-mail/message-body-search.h	Fri Dec 06 03:09:22 2002 +0200
@@ -6,7 +6,7 @@
    is invalid. If charset is NULL, the key isn't assumed to be in any
    specific charset but is compared to message data without any translation. */
 int message_body_search(const char *key, const char *charset,
-			int *unknown_charset, IBuffer *inbuf,
+			int *unknown_charset, IStream *input,
 			MessagePart *part, int search_header);
 
 #endif
--- a/src/lib-mail/message-parser.c	Fri Dec 06 00:37:33 2002 +0200
+++ b/src/lib-mail/message-parser.c	Fri Dec 06 03:09:22 2002 +0200
@@ -1,7 +1,7 @@
 /* Copyright (C) 2002 Timo Sirainen */
 
 #include "lib.h"
-#include "ibuffer.h"
+#include "istream.h"
 #include "rfc822-tokenize.h"
 #include "message-content-parser.h"
 #include "message-parser.h"
@@ -27,12 +27,12 @@
 	void *context;
 } MessageParseContext;
 
-static MessagePart *message_parse_part(IBuffer *inbuf,
+static MessagePart *message_parse_part(IStream *input,
 				       MessageParseContext *parse_ctx);
-static MessagePart *message_parse_body(IBuffer *inbuf,
+static MessagePart *message_parse_body(IStream *input,
 				       MessageBoundary *boundaries,
 				       MessageSize *body_size);
-static MessagePart *message_skip_boundary(IBuffer *inbuf,
+static MessagePart *message_skip_boundary(IStream *input,
 					  MessageBoundary *boundaries,
 					  MessageSize *boundary_size);
 
@@ -136,7 +136,7 @@
 	}
 }
 
-static MessagePart *message_parse_multipart(IBuffer *inbuf,
+static MessagePart *message_parse_multipart(IStream *input,
 					    MessageParseContext *parse_ctx)
 {
 	MessagePart *parent_part, *next_part, *part;
@@ -157,7 +157,7 @@
 
 	/* skip the data before the first boundary */
 	parent_part = parse_ctx->part;
-	next_part = message_skip_boundary(inbuf, parse_ctx->boundaries,
+	next_part = message_skip_boundary(input, parse_ctx->boundaries,
 					  &parent_part->body_size);
 
 	/* now, parse the parts */
@@ -166,7 +166,7 @@
 		part = message_part_append(parse_ctx->pool, parent_part);
 
                 parse_ctx->part = part;
-		next_part = message_parse_part(inbuf, parse_ctx);
+		next_part = message_parse_part(input, parse_ctx);
 
 		/* update our size */
 		message_size_add_part(&parent_part->body_size, part);
@@ -175,7 +175,7 @@
 			break;
 
 		/* skip the boundary */
-		next_part = message_skip_boundary(inbuf, parse_ctx->boundaries,
+		next_part = message_skip_boundary(input, parse_ctx->boundaries,
 						  &parent_part->body_size);
 	}
 
@@ -185,13 +185,13 @@
 	return next_part;
 }
 
-static MessagePart *message_parse_part(IBuffer *inbuf,
+static MessagePart *message_parse_part(IStream *input,
 				       MessageParseContext *parse_ctx)
 {
 	MessagePart *next_part, *part;
 	uoff_t hdr_size;
 
-	message_parse_header(parse_ctx->part, inbuf,
+	message_parse_header(parse_ctx->part, input,
 			     &parse_ctx->part->header_size,
 			     parse_header_field, parse_ctx);
 
@@ -199,7 +199,7 @@
 	hdr_size = parse_ctx->part->header_size.physical_size;
 
 	if (parse_ctx->last_boundary != NULL)
-		return message_parse_multipart(inbuf, parse_ctx);
+		return message_parse_multipart(input, parse_ctx);
 
 	if (parse_ctx->last_content_type == NULL) {
 		if (parse_ctx->part->parent != NULL &&
@@ -226,7 +226,7 @@
 		part = message_part_append(parse_ctx->pool, parse_ctx->part);
 
 		parse_ctx->part = part;
-		next_part = message_parse_part(inbuf, parse_ctx);
+		next_part = message_parse_part(input, parse_ctx);
 		parse_ctx->part = part->parent;
 
 		/* our body size is the size of header+body in message/rfc822 */
@@ -234,14 +234,14 @@
 	} else {
 		/* normal message, read until the next boundary */
 		part = parse_ctx->part;
-		next_part = message_parse_body(inbuf, parse_ctx->boundaries,
+		next_part = message_parse_body(input, parse_ctx->boundaries,
 					       &part->body_size);
 	}
 
 	return next_part;
 }
 
-MessagePart *message_parse(Pool pool, IBuffer *inbuf,
+MessagePart *message_parse(Pool pool, IStream *input,
 			   MessageHeaderFunc func, void *context)
 {
 	MessagePart *part;
@@ -254,20 +254,20 @@
 	parse_ctx.part = part = p_new(pool, MessagePart, 1);
 
 	t_push();
-	message_parse_part(inbuf, &parse_ctx);
+	message_parse_part(input, &parse_ctx);
 	t_pop();
 	return part;
 }
 
 /* skip over to next line increasing message size */
-static void message_skip_line(IBuffer *inbuf, MessageSize *msg_size)
+static void message_skip_line(IStream *input, MessageSize *msg_size)
 {
 	const unsigned char *msg;
 	size_t i, size, startpos;
 
 	startpos = 0;
 
-	while (i_buffer_read_data(inbuf, &msg, &size, startpos) > 0) {
+	while (i_stream_read_data(input, &msg, &size, startpos) > 0) {
 		for (i = startpos; i < size; i++) {
 			if (msg[i] == '\n') {
 				if (msg_size != NULL) {
@@ -285,7 +285,7 @@
 		}
 
 		/* leave the last character, it may be \r */
-		i_buffer_skip(inbuf, i - 1);
+		i_stream_skip(input, i - 1);
 		startpos = 1;
 
 		if (msg_size != NULL) {
@@ -294,7 +294,7 @@
 		}
 	}
 
-	i_buffer_skip(inbuf, startpos);
+	i_stream_skip(input, startpos);
 
 	if (msg_size != NULL) {
 		msg_size->physical_size += startpos;
@@ -302,7 +302,7 @@
 	}
 }
 
-void message_parse_header(MessagePart *part, IBuffer *inbuf,
+void message_parse_header(MessagePart *part, IStream *input,
 			  MessageSize *hdr_size,
 			  MessageHeaderFunc func, void *context)
 {
@@ -317,12 +317,12 @@
 	missing_cr_count = startpos = line_start = 0;
 	colon_pos = UINT_MAX;
 	for (;;) {
-		ret = i_buffer_read_data(inbuf, &msg, &size, startpos+1);
+		ret = i_stream_read_data(input, &msg, &size, startpos+1);
 		if (ret == -2) {
 			/* overflow, line is too long. just skip it. */
 			i_assert(size > 2);
 
-                        message_skip_line(inbuf, hdr_size);
+                        message_skip_line(input, hdr_size);
 			startpos = line_start = 0;
 			colon_pos = UINT_MAX;
 			continue;
@@ -412,13 +412,13 @@
 			colon_pos -= line_start;
 		if (hdr_size != NULL)
 			hdr_size->physical_size += line_start;
-		i_buffer_skip(inbuf, line_start);
+		i_stream_skip(input, line_start);
 
 		startpos = i-line_start;
 		line_start = 0;
 	}
 
-	i_buffer_skip(inbuf, startpos);
+	i_stream_skip(input, startpos);
 
 	if (hdr_size != NULL) {
 		hdr_size->physical_size += startpos;
@@ -451,7 +451,7 @@
    [\r]\n before the boundary, otherwise leave it right after the known
    boundary so the ending "--" can be checked. */
 static MessageBoundary *
-message_find_boundary(IBuffer *inbuf, MessageBoundary *boundaries,
+message_find_boundary(IStream *input, MessageBoundary *boundaries,
 		      MessageSize *msg_size, int skip_over)
 {
 	MessageBoundary *boundary;
@@ -461,7 +461,7 @@
 	boundary = NULL;
 	missing_cr_count = startpos = line_start = 0;
 
-	while (i_buffer_read_data(inbuf, &msg, &size, startpos) > 0) {
+	while (i_stream_read_data(input, &msg, &size, startpos) > 0) {
 		for (i = startpos; i < size; i++) {
 			if (msg[i] != '\n')
 				continue;
@@ -511,7 +511,7 @@
 			line_start -= i;
 		}
 
-		i_buffer_skip(inbuf, i);
+		i_stream_skip(input, i);
 		msg_size->physical_size += i;
 		msg_size->virtual_size += i;
 
@@ -535,7 +535,7 @@
 		startpos = line_start;
 	}
 
-	i_buffer_skip(inbuf, startpos);
+	i_stream_skip(input, startpos);
 	msg_size->physical_size += startpos;
 	msg_size->virtual_size += startpos + missing_cr_count;
 
@@ -544,17 +544,17 @@
 	return boundary;
 }
 
-static MessagePart *message_parse_body(IBuffer *inbuf,
+static MessagePart *message_parse_body(IStream *input,
 				       MessageBoundary *boundaries,
 				       MessageSize *body_size)
 {
 	MessageBoundary *boundary;
 
 	if (boundaries == NULL) {
-		message_get_body_size(inbuf, body_size, (uoff_t)-1);
+		message_get_body_size(input, body_size, (uoff_t)-1);
 		return NULL;
 	} else {
-		boundary = message_find_boundary(inbuf, boundaries,
+		boundary = message_find_boundary(input, boundaries,
 						 body_size, FALSE);
 		return boundary == NULL ? NULL : boundary->part;
 	}
@@ -562,7 +562,7 @@
 
 /* skip data until next boundary is found. if it's end boundary,
    skip the footer as well. */
-static MessagePart *message_skip_boundary(IBuffer *inbuf,
+static MessagePart *message_skip_boundary(IStream *input,
 					  MessageBoundary *boundaries,
 					  MessageSize *boundary_size)
 {
@@ -571,22 +571,22 @@
 	size_t size;
 	int end_boundary;
 
-	boundary = message_find_boundary(inbuf, boundaries,
+	boundary = message_find_boundary(input, boundaries,
 					 boundary_size, TRUE);
 	if (boundary == NULL)
 		return NULL;
 
 	/* now, see if it's end boundary */
 	end_boundary = FALSE;
-	if (i_buffer_read_data(inbuf, &msg, &size, 1) > 0)
+	if (i_stream_read_data(input, &msg, &size, 1) > 0)
 		end_boundary = msg[0] == '-' && msg[1] == '-';
 
 	/* skip the rest of the line */
-	message_skip_line(inbuf, boundary_size);
+	message_skip_line(input, boundary_size);
 
 	if (end_boundary) {
 		/* skip the footer */
-		return message_parse_body(inbuf, boundaries, boundary_size);
+		return message_parse_body(input, boundaries, boundary_size);
 	}
 
 	return boundary == NULL ? NULL : boundary->part;
--- a/src/lib-mail/message-parser.h	Fri Dec 06 00:37:33 2002 +0200
+++ b/src/lib-mail/message-parser.h	Fri Dec 06 03:09:22 2002 +0200
@@ -44,15 +44,15 @@
 				  void *context);
 
 /* func is called for each field in message header. */
-MessagePart *message_parse(Pool pool, IBuffer *inbuf,
+MessagePart *message_parse(Pool pool, IStream *input,
 			   MessageHeaderFunc func, void *context);
 
 /* Call func for each field in message header. Fills the hdr_size.
    part can be NULL, just make sure your header function works with it.
    This function doesn't use data stack so your header function may save
-   values to it. When finished, inbuf will point to beginning of message
+   values to it. When finished, input will point to beginning of message
    body. */
-void message_parse_header(MessagePart *part, IBuffer *inbuf,
+void message_parse_header(MessagePart *part, IStream *input,
 			  MessageSize *hdr_size,
 			  MessageHeaderFunc func, void *context);
 
--- a/src/lib-mail/message-send.c	Fri Dec 06 00:37:33 2002 +0200
+++ b/src/lib-mail/message-send.c	Fri Dec 06 03:09:22 2002 +0200
@@ -1,12 +1,12 @@
 /* Copyright (C) 2002 Timo Sirainen */
 
 #include "lib.h"
-#include "ibuffer.h"
-#include "obuffer.h"
+#include "istream.h"
+#include "ostream.h"
 #include "message-send.h"
 #include "message-size.h"
 
-int message_send(OBuffer *outbuf, IBuffer *inbuf, MessageSize *msg_size,
+int message_send(OStream *output, IStream *input, MessageSize *msg_size,
 		 uoff_t virtual_skip, uoff_t max_virtual_size)
 {
 	const unsigned char *msg;
@@ -23,21 +23,21 @@
 
 	if (msg_size->physical_size == msg_size->virtual_size) {
 		/* no need to kludge with CRs, we can use sendfile() */
-		i_buffer_skip(inbuf, virtual_skip);
+		i_stream_skip(input, virtual_skip);
 
-		old_limit = inbuf->v_limit;
-		limit = inbuf->v_offset + max_virtual_size;
-		i_buffer_set_read_limit(inbuf, I_MIN(limit, old_limit));
-		ret = o_buffer_send_ibuffer(outbuf, inbuf) > 0;
-		i_buffer_set_read_limit(inbuf, old_limit);
+		old_limit = input->v_limit;
+		limit = input->v_offset + max_virtual_size;
+		i_stream_set_read_limit(input, I_MIN(limit, old_limit));
+		ret = o_stream_send_istream(output, input) > 0;
+		i_stream_set_read_limit(input, old_limit);
 
 		return ret;
 	}
 
-	message_skip_virtual(inbuf, virtual_skip, NULL, &cr_skipped);
+	message_skip_virtual(input, virtual_skip, NULL, &cr_skipped);
 
 	/* go through the message data and insert CRs where needed.  */
-	while (i_buffer_read_data(inbuf, &msg, &size, 0) > 0) {
+	while (i_stream_read_data(input, &msg, &size, 0) > 0) {
 		add_cr = FALSE;
 		for (i = 0; i < size; i++) {
 			if (msg[i] == '\n') {
@@ -60,11 +60,11 @@
 			}
 		}
 
-		if (o_buffer_send(outbuf, msg, i) < 0)
+		if (o_stream_send(output, msg, i) < 0)
 			return FALSE;
 
 		if (add_cr) {
-			if (o_buffer_send(outbuf, "\r", 1) < 0)
+			if (o_stream_send(output, "\r", 1) < 0)
 				return FALSE;
 			cr_skipped = TRUE;
 		} else {
@@ -75,7 +75,7 @@
 		if (max_virtual_size == 0)
 			break;
 
-		i_buffer_skip(inbuf, i);
+		i_stream_skip(input, i);
 	}
 
 	return TRUE;
--- a/src/lib-mail/message-send.h	Fri Dec 06 00:37:33 2002 +0200
+++ b/src/lib-mail/message-send.h	Fri Dec 06 03:09:22 2002 +0200
@@ -5,9 +5,9 @@
 
 /* Send message to client inserting CRs if needed. Only max_virtual_size
    bytes if sent (relative to virtual_skip), if you want it unlimited,
-   use (uoff_t)-1. Remember that if inbuf begins with LF, CR is inserted
+   use (uoff_t)-1. Remember that if input begins with LF, CR is inserted
    before it unless virtual_skip = 1. Returns TRUE if successful. */
-int message_send(OBuffer *outbuf, IBuffer *inbuf, MessageSize *msg_size,
+int message_send(OStream *output, IStream *input, MessageSize *msg_size,
 		 uoff_t virtual_skip, uoff_t max_virtual_size);
 
 #endif
--- a/src/lib-mail/message-size.c	Fri Dec 06 00:37:33 2002 +0200
+++ b/src/lib-mail/message-size.c	Fri Dec 06 03:09:22 2002 +0200
@@ -1,11 +1,11 @@
 /* Copyright (C) 2002 Timo Sirainen */
 
 #include "lib.h"
-#include "ibuffer.h"
+#include "istream.h"
 #include "message-parser.h"
 #include "message-size.h"
 
-void message_get_header_size(IBuffer *inbuf, MessageSize *hdr)
+void message_get_header_size(IStream *input, MessageSize *hdr)
 {
 	const unsigned char *msg;
 	size_t i, size, startpos, missing_cr_count;
@@ -13,7 +13,7 @@
 	memset(hdr, 0, sizeof(MessageSize));
 
 	missing_cr_count = 0; startpos = 0;
-	while (i_buffer_read_data(inbuf, &msg, &size, startpos) > 0) {
+	while (i_stream_read_data(input, &msg, &size, startpos) > 0) {
 		for (i = startpos; i < size; i++) {
 			if (msg[i] != '\n')
 				continue;
@@ -44,18 +44,18 @@
 
 		/* leave the last two characters, they may be \r\n */
 		startpos = size == 1 ? 1 : 2;
-		i_buffer_skip(inbuf, i - startpos);
+		i_stream_skip(input, i - startpos);
 
 		hdr->physical_size += i - startpos;
 	}
-	i_buffer_skip(inbuf, startpos);
+	i_stream_skip(input, startpos);
 	hdr->physical_size += startpos;
 
 	hdr->virtual_size = hdr->physical_size + missing_cr_count;
 	i_assert(hdr->virtual_size >= hdr->physical_size);
 }
 
-void message_get_body_size(IBuffer *inbuf, MessageSize *body,
+void message_get_body_size(IStream *input, MessageSize *body,
 			   uoff_t max_virtual_size)
 {
 	const unsigned char *msg;
@@ -65,7 +65,7 @@
 
 	missing_cr_count = 0; startpos = 0;
 	while (max_virtual_size != 0 &&
-	       i_buffer_read_data(inbuf, &msg, &size, startpos) > 0) {
+	       i_stream_read_data(input, &msg, &size, startpos) > 0) {
 		for (i = startpos; i < size && max_virtual_size != 0; i++) {
 			if (max_virtual_size > 0)
 				max_virtual_size--;
@@ -91,19 +91,19 @@
 		}
 
 		/* leave the last character, it may be \r */
-		i_buffer_skip(inbuf, i - 1);
+		i_stream_skip(input, i - 1);
 		startpos = 1;
 
 		body->physical_size += i - 1;
 	}
-	i_buffer_skip(inbuf, startpos);
+	i_stream_skip(input, startpos);
 	body->physical_size += startpos;
 
 	body->virtual_size = body->physical_size + missing_cr_count;
 	i_assert(body->virtual_size >= body->physical_size);
 }
 
-void message_skip_virtual(IBuffer *inbuf, uoff_t virtual_skip,
+void message_skip_virtual(IStream *input, uoff_t virtual_skip,
 			  MessageSize *msg_size, int *cr_skipped)
 {
 	const unsigned char *msg;
@@ -114,7 +114,7 @@
 		return;
 
 	startpos = 0;
-	while (i_buffer_read_data(inbuf, &msg, &size, startpos) > 0) {
+	while (i_stream_read_data(input, &msg, &size, startpos) > 0) {
 		for (i = startpos; i < size && virtual_skip > 0; i++) {
 			virtual_skip--;
 
@@ -151,12 +151,12 @@
 		}
 
 		if (i < size) {
-			i_buffer_skip(inbuf, i);
+			i_stream_skip(input, i);
 			break;
 		}
 
 		/* leave the last character, it may be \r */
-		i_buffer_skip(inbuf, i - 1);
+		i_stream_skip(input, i - 1);
 		startpos = 1;
 	}
 }
--- a/src/lib-mail/message-size.h	Fri Dec 06 00:37:33 2002 +0200
+++ b/src/lib-mail/message-size.h	Fri Dec 06 03:09:22 2002 +0200
@@ -3,18 +3,18 @@
 
 #include "message-parser.h"
 
-/* Calculate size of message header. Leave the inbuf point to first
+/* Calculate size of message header. Leave the input point to first
    character in body. */
-void message_get_header_size(IBuffer *inbuf, MessageSize *hdr);
+void message_get_header_size(IStream *input, MessageSize *hdr);
 /* Calculate size of message body. Read only max_virtual_size virtual bytes,
    if you want it unlimited, use (uoff_t)-1. */
-void message_get_body_size(IBuffer *inbuf, MessageSize *body,
+void message_get_body_size(IStream *input, MessageSize *body,
 			   uoff_t max_virtual_size);
 
-/* Skip number of virtual bytes from buffer. If first character is \n, and
+/* Skip number of virtual bytes from putfer. If first character is \n, and
    cr_skipped is FALSE, \r must be sent before it. msg_size is updated if
    it's not NULL. */
-void message_skip_virtual(IBuffer *inbuf, uoff_t virtual_skip,
+void message_skip_virtual(IStream *input, uoff_t virtual_skip,
 			  MessageSize *msg_size, int *cr_skipped);
 
 /* Sum contents of src into dest. */
--- a/src/lib-storage/index/index-copy.c	Fri Dec 06 00:37:33 2002 +0200
+++ b/src/lib-storage/index/index-copy.c	Fri Dec 06 03:09:22 2002 +0200
@@ -1,7 +1,7 @@
 /* Copyright (C) 2002 Timo Sirainen */
 
 #include "lib.h"
-#include "ibuffer.h"
+#include "istream.h"
 #include "mail-custom-flags.h"
 #include "index-storage.h"
 #include "index-messageset.h"
@@ -20,12 +20,12 @@
 {
 	CopyContext *ctx = context;
 	IndexMailbox *dest_ibox = NULL;
-	IBuffer *inbuf;
+	IStream *input;
 	time_t internal_date;
 	int failed, deleted;
 
-	inbuf = index->open_mail(index, rec, &internal_date, &deleted);
-	if (inbuf == NULL)
+	input = index->open_mail(index, rec, &internal_date, &deleted);
+	if (input == NULL)
 		return FALSE;
 
 	if (ctx->copy_inside_mailbox) {
@@ -37,12 +37,12 @@
 	/* save it in destination mailbox */
 	failed = !ctx->dest->save(ctx->dest, rec->msg_flags,
 				  ctx->custom_flags, internal_date, 0,
-				  inbuf, inbuf->v_limit);
+				  input, input->v_limit);
 
 	if (ctx->copy_inside_mailbox)
 		dest_ibox->delay_save_unlocking = FALSE;
 
-	i_buffer_unref(inbuf);
+	i_stream_unref(input);
 	return !failed;
 }
 
--- a/src/lib-storage/index/index-fetch-section.c	Fri Dec 06 00:37:33 2002 +0200
+++ b/src/lib-storage/index/index-fetch-section.c	Fri Dec 06 03:09:22 2002 +0200
@@ -2,8 +2,8 @@
 
 #include "lib.h"
 #include "temp-string.h"
-#include "ibuffer.h"
-#include "obuffer.h"
+#include "istream.h"
+#include "ostream.h"
 #include "rfc822-tokenize.h"
 #include "message-send.h"
 #include "index-storage.h"
@@ -43,13 +43,13 @@
 		      FetchContext *ctx, const char *prefix, int fetch_header)
 {
 	MessageSize size;
-	IBuffer *inbuf;
+	IStream *input;
 	const char *str;
 	int cr_skipped;
 
 	if (!imap_msgcache_get_rfc822_partial(ctx->cache, sect->skip,
 					      sect->max_size, fetch_header,
-					      &size, &inbuf, &cr_skipped)) {
+					      &size, &input, &cr_skipped)) {
 		i_error("Couldn't get BODY[] for UID %u (index %s)",
 			rec->uid, ctx->index->filepath);
 		return FALSE;
@@ -57,13 +57,13 @@
 
 	str = t_strdup_printf("%s {%"PRIuUOFF_T"}\r\n",
 			      prefix, size.virtual_size);
-	if (o_buffer_send(ctx->outbuf, str, strlen(str)) < 0)
+	if (o_stream_send(ctx->output, str, strlen(str)) < 0)
 		return FALSE;
 
 	if (cr_skipped)
 		size.virtual_size++;
 
-	return message_send(ctx->outbuf, inbuf, &size,
+	return message_send(ctx->output, input, &size,
 			    cr_skipped ? 1 : 0, sect->max_size);
 }
 
@@ -139,7 +139,7 @@
 
 typedef struct {
 	TempString *dest;
-	OBuffer *outbuf;
+	OStream *output;
 	uoff_t dest_size;
 
 	uoff_t skip, max_size;
@@ -170,8 +170,8 @@
 		t_string_append_n(ctx->dest, str, size);
 	ctx->dest_size += size;
 
-	if (ctx->outbuf != NULL) {
-		if (o_buffer_send(ctx->outbuf, str, size) < 0)
+	if (ctx->output != NULL) {
+		if (o_stream_send(ctx->output, str, size) < 0)
 			return FALSE;
 	}
 	return ctx->dest_size < ctx->max_size;
@@ -220,7 +220,7 @@
 	(void)fetch_header_append(ctx, "\r\n", 2);
 }
 
-static int fetch_header_fields(IBuffer *inbuf, const char *section,
+static int fetch_header_fields(IStream *input, const char *section,
 			       FetchHeaderFieldContext *ctx)
 {
 	if (strncasecmp(section, "HEADER.FIELDS ", 14) == 0) {
@@ -238,7 +238,7 @@
 	}
 
 	ctx->dest_size = 0;
-	message_parse_header(NULL, inbuf, NULL, fetch_header_field, ctx);
+	message_parse_header(NULL, input, NULL, fetch_header_field, ctx);
 
 	i_assert(ctx->dest_size <= ctx->max_size);
 	i_assert(ctx->dest == NULL || ctx->dest->len == ctx->dest_size);
@@ -246,7 +246,7 @@
 }
 
 /* fetch wanted headers from given data */
-static int fetch_header_from(IBuffer *inbuf, OBuffer *outbuf,
+static int fetch_header_from(IStream *input, OStream *output,
 			     const char *prefix, MessageSize *size,
 			     const char *section, MailFetchBodyData *sect)
 {
@@ -261,61 +261,61 @@
 		/* all headers */
 		str = t_strdup_printf("%s {%"PRIuUOFF_T"}\r\n",
 				      prefix, size->virtual_size);
-		if (o_buffer_send(outbuf, str, strlen(str)) < 0)
+		if (o_stream_send(output, str, strlen(str)) < 0)
 			return FALSE;
-		return message_send(outbuf, inbuf, size,
+		return message_send(output, input, size,
 				    sect->skip, sect->max_size);
 	}
 
 	/* partial headers - copy the wanted fields into memory, inserting
 	   missing CRs on the way. If the header is too large, calculate 
-	   the size first and then send the data directly to output buffer. */
+	   the size first and then send the data directly to output stream. */
 
 	memset(&ctx, 0, sizeof(ctx));
 	ctx.skip = sect->skip;
 	ctx.max_size = sect->max_size;
 
 	failed = FALSE;
-	start_offset = inbuf->v_offset;
+	start_offset = input->v_offset;
 
 	t_push();
 
 	/* first pass, we need at least the size */
 	if (size->virtual_size > MAX_HEADER_BUFFER_SIZE &&
 	    sect->max_size > MAX_HEADER_BUFFER_SIZE) {
-		if (!fetch_header_fields(inbuf, section, &ctx))
+		if (!fetch_header_fields(input, section, &ctx))
 			failed = TRUE;
 
 		i_assert(ctx.dest_size <= size->virtual_size);
 	} else {
 		ctx.dest = t_string_new(size->virtual_size < 4096 ?
 					size->virtual_size : 4096);
-		if (!fetch_header_fields(inbuf, section, &ctx))
+		if (!fetch_header_fields(input, section, &ctx))
 			failed = TRUE;
 	}
 
 	if (!failed) {
 		str = t_strdup_printf("%s {%"PRIuUOFF_T"}\r\n",
 				      prefix, ctx.dest_size);
-		if (o_buffer_send(outbuf, str, strlen(str)) < 0)
+		if (o_stream_send(output, str, strlen(str)) < 0)
 			failed = TRUE;
 	}
 
 	if (!failed) {
 		if (ctx.dest == NULL) {
-			/* second pass, write the data to output buffer */
+			/* second pass, write the data to output stream */
 			uoff_t first_size = ctx.dest_size;
 
-			ctx.outbuf = outbuf;
-			i_buffer_seek(inbuf, start_offset);
+			ctx.output = output;
+			i_stream_seek(input, start_offset);
 
 			if (!failed &&
-			    !fetch_header_fields(inbuf, section, &ctx))
+			    !fetch_header_fields(input, section, &ctx))
 				failed = TRUE;
 
 			i_assert(first_size == ctx.dest_size);
 		} else {
-			if (o_buffer_send(outbuf, ctx.dest->str,
+			if (o_stream_send(output, ctx.dest->str,
 					  ctx.dest->len) < 0)
 				failed = TRUE;
 		}
@@ -330,12 +330,12 @@
 			const char *prefix)
 {
 	MessageSize hdr_size;
-	IBuffer *inbuf;
+	IStream *input;
 
-	if (!imap_msgcache_get_rfc822(ctx->cache, &inbuf, &hdr_size, NULL))
+	if (!imap_msgcache_get_rfc822(ctx->cache, &input, &hdr_size, NULL))
 		return FALSE;
 
-	return fetch_header_from(inbuf, ctx->outbuf, prefix, &hdr_size,
+	return fetch_header_from(input, ctx->output, prefix, &hdr_size,
 				 sect->section, sect);
 }
 
@@ -389,25 +389,25 @@
 static int fetch_part_body(MessagePart *part, MailFetchBodyData *sect,
 			   FetchContext *ctx, const char *prefix)
 {
-	IBuffer *inbuf;
+	IStream *input;
 	const char *str;
 	uoff_t skip_pos;
 
-	if (!imap_msgcache_get_data(ctx->cache, &inbuf))
+	if (!imap_msgcache_get_data(ctx->cache, &input))
 		return FALSE;
 
 	/* jump to beginning of wanted data */
 	skip_pos = part->physical_pos + part->header_size.physical_size;
-	i_buffer_skip(inbuf, skip_pos);
+	i_stream_skip(input, skip_pos);
 
 	str = t_strdup_printf("%s {%"PRIuUOFF_T"}\r\n",
 			      prefix, part->body_size.virtual_size);
-	if (o_buffer_send(ctx->outbuf, str, strlen(str)) < 0)
+	if (o_stream_send(ctx->output, str, strlen(str)) < 0)
 		return FALSE;
 
 	/* FIXME: potential performance problem with big messages:
 	   FETCH BODY[1]<100000..1024>, hopefully no clients do this */
-	return message_send(ctx->outbuf, inbuf, &part->body_size,
+	return message_send(ctx->output, input, &part->body_size,
 			    sect->skip, sect->max_size);
 }
 
@@ -416,13 +416,13 @@
 			     MailFetchBodyData *sect, FetchContext *ctx,
 			     const char *prefix)
 {
-	IBuffer *inbuf;
+	IStream *input;
 
-	if (!imap_msgcache_get_data(ctx->cache, &inbuf))
+	if (!imap_msgcache_get_data(ctx->cache, &input))
 		return FALSE;
 
-	i_buffer_skip(inbuf, part->physical_pos);
-	return fetch_header_from(inbuf, ctx->outbuf, prefix, &part->header_size,
+	i_stream_skip(input, part->physical_pos);
+	return fetch_header_from(input, ctx->output, prefix, &part->header_size,
 				 section, sect);
 }
 
--- a/src/lib-storage/index/index-fetch.c	Fri Dec 06 00:37:33 2002 +0200
+++ b/src/lib-storage/index/index-fetch.c	Fri Dec 06 03:09:22 2002 +0200
@@ -1,7 +1,7 @@
 /* Copyright (C) 2002 Timo Sirainen */
 
 #include "lib.h"
-#include "obuffer.h"
+#include "ostream.h"
 #include "temp-string.h"
 #include "mail-custom-flags.h"
 #include "index-storage.h"
@@ -119,10 +119,10 @@
 static int index_fetch_send_rfc822(MailIndexRecord *rec, FetchContext *ctx)
 {
 	MessageSize hdr_size, body_size;
-	IBuffer *inbuf;
+	IStream *input;
 	const char *str;
 
-	if (!imap_msgcache_get_rfc822(ctx->cache, &inbuf,
+	if (!imap_msgcache_get_rfc822(ctx->cache, &input,
 				      &hdr_size, &body_size)) {
 		mail_storage_set_critical(ctx->storage,
 			"Couldn't get RFC822 for UID %u (index %s)",
@@ -135,22 +135,22 @@
 	if (ctx->first) {
 		str++; ctx->first = FALSE;
 	}
-	if (o_buffer_send(ctx->outbuf, str, strlen(str)) < 0)
+	if (o_stream_send(ctx->output, str, strlen(str)) < 0)
 		return FALSE;
 
 	body_size.physical_size += hdr_size.physical_size;
 	body_size.virtual_size += hdr_size.virtual_size;
-	return message_send(ctx->outbuf, inbuf, &body_size, 0, (uoff_t)-1);
+	return message_send(ctx->output, input, &body_size, 0, (uoff_t)-1);
 }
 
 static int index_fetch_send_rfc822_header(MailIndexRecord *rec,
 					  FetchContext *ctx)
 {
 	MessageSize hdr_size;
-	IBuffer *inbuf;
+	IStream *input;
 	const char *str;
 
-	if (!imap_msgcache_get_rfc822(ctx->cache, &inbuf, &hdr_size, NULL)) {
+	if (!imap_msgcache_get_rfc822(ctx->cache, &input, &hdr_size, NULL)) {
 		mail_storage_set_critical(ctx->storage,
 			"Couldn't get RFC822.HEADER for UID %u (index %s)",
 			rec->uid, ctx->index->filepath);
@@ -162,19 +162,19 @@
 	if (ctx->first) {
 		str++; ctx->first = FALSE;
 	}
-	if (o_buffer_send(ctx->outbuf, str, strlen(str)) < 0)
+	if (o_stream_send(ctx->output, str, strlen(str)) < 0)
 		return FALSE;
 
-	return message_send(ctx->outbuf, inbuf, &hdr_size, 0, (uoff_t)-1);
+	return message_send(ctx->output, input, &hdr_size, 0, (uoff_t)-1);
 }
 
 static int index_fetch_send_rfc822_text(MailIndexRecord *rec, FetchContext *ctx)
 {
 	MessageSize body_size;
-	IBuffer *inbuf;
+	IStream *input;
 	const char *str;
 
-	if (!imap_msgcache_get_rfc822(ctx->cache, &inbuf, NULL, &body_size)) {
+	if (!imap_msgcache_get_rfc822(ctx->cache, &input, NULL, &body_size)) {
 		mail_storage_set_critical(ctx->storage,
 			"Couldn't get RFC822.TEXT for UID %u (index %s)",
 			rec->uid, ctx->index->filepath);
@@ -186,10 +186,10 @@
 	if (ctx->first) {
 		str++; ctx->first = FALSE;
 	}
-	if (o_buffer_send(ctx->outbuf, str, strlen(str)) < 0)
+	if (o_stream_send(ctx->output, str, strlen(str)) < 0)
 		return FALSE;
 
-	return message_send(ctx->outbuf, inbuf, &body_size, 0, (uoff_t)-1);
+	return message_send(ctx->output, input, &body_size, 0, (uoff_t)-1);
 }
 
 static ImapCacheField index_get_cache(MailFetchData *fetch_data)
@@ -303,7 +303,7 @@
 			if (!ctx->first)
 				ctx->str->len--;
 
-			if (o_buffer_send(ctx->outbuf, ctx->str->str,
+			if (o_stream_send(ctx->output, ctx->str->str,
 					  ctx->str->len) < 0)
 				break;
 		}
@@ -331,7 +331,7 @@
 	} while (0);
 
 	if (data_written) {
-		if (o_buffer_send(ctx->outbuf, ")\r\n", 3) < 0)
+		if (o_stream_send(ctx->output, ")\r\n", 3) < 0)
 			failed = TRUE;
 	}
 
@@ -340,7 +340,7 @@
 }
 
 int index_storage_fetch(Mailbox *box, MailFetchData *fetch_data,
-			OBuffer *outbuf, int *all_found)
+			OStream *output, int *all_found)
 {
 	IndexMailbox *ibox = (IndexMailbox *) box;
 	FetchContext ctx;
@@ -391,7 +391,7 @@
         ctx.custom_flags_count = MAIL_CUSTOM_FLAGS_COUNT;
 
 	ctx.fetch_data = fetch_data;
-	ctx.outbuf = outbuf;
+	ctx.output = output;
 
 	ret = index_messageset_foreach(ibox, fetch_data->messageset,
 				       fetch_data->uidset,
--- a/src/lib-storage/index/index-fetch.h	Fri Dec 06 00:37:33 2002 +0200
+++ b/src/lib-storage/index/index-fetch.h	Fri Dec 06 03:09:22 2002 +0200
@@ -11,7 +11,7 @@
 	unsigned int custom_flags_count;
 
 	MailFetchData *fetch_data;
-	OBuffer *outbuf;
+	OStream *output;
 	TempString *str;
 	int update_seen, failed;
 	int first;
--- a/src/lib-storage/index/index-msgcache.c	Fri Dec 06 00:37:33 2002 +0200
+++ b/src/lib-storage/index/index-msgcache.c	Fri Dec 06 03:09:22 2002 +0200
@@ -1,7 +1,7 @@
 /* Copyright (C) 2002 Timo Sirainen */
 
 #include "lib.h"
-#include "ibuffer.h"
+#include "istream.h"
 #include "imap-date.h"
 #include "imap-message-cache.h"
 #include "message-part-serialize.h"
@@ -71,7 +71,7 @@
 				  full_virtual_size, ctx);
 }
 
-static IBuffer *index_msgcache_open_mail(void *context)
+static IStream *index_msgcache_open_mail(void *context)
 {
 	IndexMsgcacheContext *ctx = context;
 	int deleted;
@@ -80,11 +80,11 @@
 				     &ctx->internal_date, &deleted);
 }
 
-static IBuffer *index_msgcache_inbuf_rewind(IBuffer *inbuf,
-					    void *context __attr_unused__)
+static IStream *index_msgcache_stream_rewind(IStream *input,
+					     void *context __attr_unused__)
 {
-	i_buffer_seek(inbuf, 0);
-	return inbuf;
+	i_stream_seek(input, 0);
+	return input;
 }
 
 static const char *index_msgcache_get_cached_field(ImapCacheField field,
@@ -169,7 +169,7 @@
 
 ImapMessageCacheIface index_msgcache_iface = {
 	index_msgcache_open_mail,
-	index_msgcache_inbuf_rewind,
+	index_msgcache_stream_rewind,
 	index_msgcache_get_cached_field,
 	index_msgcache_get_cached_parts,
 	index_msgcache_get_internal_date
--- a/src/lib-storage/index/index-save.c	Fri Dec 06 00:37:33 2002 +0200
+++ b/src/lib-storage/index/index-save.c	Fri Dec 06 03:09:22 2002 +0200
@@ -1,15 +1,15 @@
 /* Copyright (C) 2002 Timo Sirainen */
 
 #include "lib.h"
-#include "ibuffer.h"
-#include "obuffer.h"
+#include "istream.h"
+#include "ostream.h"
 #include "write-full.h"
 #include "index-storage.h"
 
 #include <stdlib.h>
 #include <unistd.h>
 
-static int write_with_crlf(OBuffer *outbuf, const unsigned char *data,
+static int write_with_crlf(OStream *output, const unsigned char *data,
 			   size_t size)
 {
 	size_t i, start;
@@ -20,9 +20,9 @@
 	for (i = 0; i < size; i++) {
 		if (data[i] == '\n' && (i == 0 || data[i-1] != '\r')) {
 			/* missing CR */
-			if (o_buffer_send(outbuf, data + start, i - start) < 0)
+			if (o_stream_send(output, data + start, i - start) < 0)
 				return -1;
-			if (o_buffer_send(outbuf, "\r", 1) < 0)
+			if (o_stream_send(output, "\r", 1) < 0)
 				return -1;
 
 			/* \n is written next time */
@@ -34,13 +34,13 @@
 	if (data[size-1] == '\r')
 		size--;
 
-	if (o_buffer_send(outbuf, data + start, size - start) < 0)
+	if (o_stream_send(output, data + start, size - start) < 0)
 		return -1;
 
 	return size;
 }
 
-static int write_with_lf(OBuffer *outbuf, const unsigned char *data,
+static int write_with_lf(OStream *output, const unsigned char *data,
 			 size_t size)
 {
 	size_t i, start;
@@ -51,7 +51,7 @@
 	for (i = 0; i < size; i++) {
 		if (data[i] == '\n' && i > 0 && data[i-1] == '\r') {
 			/* \r\n - skip \r */
-			if (o_buffer_send(outbuf, data + start,
+			if (o_stream_send(output, data + start,
 					   i - start - 1) < 0)
 				return -1;
 
@@ -64,16 +64,16 @@
 	if (data[size-1] == '\r')
 		size--;
 
-	if (o_buffer_send(outbuf, data + start, size - start) < 0)
+	if (o_stream_send(output, data + start, size - start) < 0)
 		return -1;
 
 	return size;
 }
 
 int index_storage_save(MailStorage *storage, const char *path,
-		       IBuffer *inbuf, OBuffer *outbuf, uoff_t data_size)
+		       IStream *input, OStream *output, uoff_t data_size)
 {
-	int (*write_func)(OBuffer *, const unsigned char *, size_t);
+	int (*write_func)(OStream *, const unsigned char *, size_t);
 	const unsigned char *data;
 	size_t size;
 	ssize_t ret;
@@ -83,9 +83,9 @@
 
 	failed = FALSE;
 	while (data_size > 0) {
-		ret = i_buffer_read(inbuf);
+		ret = i_stream_read(input);
 		if (ret < 0) {
-			errno = inbuf->buf_errno;
+			errno = input->stream_errno;
 			if (errno == 0) {
 				mail_storage_set_error(storage,
 					"Client disconnected");
@@ -99,14 +99,14 @@
 			return FALSE;
 		}
 
-		data = i_buffer_get_data(inbuf, &size);
+		data = i_stream_get_data(input, &size);
 		if (size > data_size)
 			size = (size_t)data_size;
 
 		if (!failed) {
-			ret = write_func(outbuf, data, size);
+			ret = write_func(output, data, size);
 			if (ret < 0) {
-				errno = outbuf->buf_errno;
+				errno = output->stream_errno;
 				if (errno == ENOSPC) {
 					mail_storage_set_error(storage,
 						"Not enough disk space");
@@ -122,7 +122,7 @@
 		}
 
 		data_size -= size;
-		i_buffer_skip(inbuf, size);
+		i_stream_skip(input, size);
 	}
 
 	return !failed;
--- a/src/lib-storage/index/index-search.c	Fri Dec 06 00:37:33 2002 +0200
+++ b/src/lib-storage/index/index-search.c	Fri Dec 06 03:09:22 2002 +0200
@@ -1,8 +1,8 @@
 /* Copyright (C) 2002 Timo Sirainen */
 
 #include "lib.h"
-#include "ibuffer.h"
-#include "obuffer.h"
+#include "istream.h"
+#include "ostream.h"
 #include "mmap-util.h"
 #include "rfc822-tokenize.h"
 #include "rfc822-date.h"
@@ -50,7 +50,7 @@
 
 typedef struct {
         SearchIndexContext *index_ctx;
-	IBuffer *inbuf;
+	IStream *input;
 	MessagePart *part;
 } SearchBodyContext;
 
@@ -533,10 +533,10 @@
 		return;
 
 	if (arg->type == SEARCH_TEXT || arg->type == SEARCH_BODY) {
-		i_buffer_seek(ctx->inbuf, 0);
+		i_stream_seek(ctx->input, 0);
 		ret = message_body_search(arg->value.str,
 					  ctx->index_ctx->charset,
-					  &unknown_charset, ctx->inbuf,
+					  &unknown_charset, ctx->input,
 					  ctx->part, arg->type == SEARCH_TEXT);
 
 		if (ret < 0) {
@@ -550,7 +550,7 @@
 
 static int search_arg_match_text(MailSearchArg *args, SearchIndexContext *ctx)
 {
-	IBuffer *inbuf;
+	IStream *input;
 	int have_headers, have_body, have_text;
 
 	/* first check what we need to use */
@@ -561,7 +561,7 @@
 	if (have_headers || have_text) {
 		SearchHeaderContext hdr_ctx;
 
-		if (!imap_msgcache_get_data(search_open_cache(ctx), &inbuf))
+		if (!imap_msgcache_get_data(search_open_cache(ctx), &input))
 			return FALSE;
 
 		memset(&hdr_ctx, 0, sizeof(hdr_ctx));
@@ -569,10 +569,10 @@
 		hdr_ctx.custom_header = TRUE;
 		hdr_ctx.args = args;
 
-		message_parse_header(NULL, inbuf, NULL,
+		message_parse_header(NULL, input, NULL,
 				     search_header, &hdr_ctx);
 	} else {
-		if (!imap_msgcache_get_rfc822(search_open_cache(ctx), &inbuf,
+		if (!imap_msgcache_get_rfc822(search_open_cache(ctx), &input,
 					      NULL, NULL))
 			return FALSE;
 	}
@@ -582,7 +582,7 @@
 
 		memset(&body_ctx, 0, sizeof(body_ctx));
 		body_ctx.index_ctx = ctx;
-		body_ctx.inbuf = inbuf;
+		body_ctx.input = input;
 		body_ctx.part = imap_msgcache_get_parts(search_open_cache(ctx));
 
 		mail_search_args_foreach(args, search_body, &body_ctx);
@@ -757,7 +757,7 @@
 
 static int search_messages(IndexMailbox *ibox, const char *charset,
 			   MailSearchArg *args, MailSortContext *sort_ctx,
-			   OBuffer *outbuf, int uid_result)
+			   OStream *output, int uid_result)
 {
 	SearchIndexContext ctx;
 	MailIndexRecord *rec;
@@ -831,7 +831,7 @@
 					len = i_snprintf(num, sizeof(num),
 							 " %u", uid_result ?
 							 rec->uid : client_seq);
-					o_buffer_send(outbuf, num, len);
+					o_stream_send(output, num, len);
 				} else {
 					mail_sort_input(sort_ctx, rec->uid);
 				}
@@ -850,7 +850,7 @@
 }
 
 int index_storage_search(Mailbox *box, const char *charset, MailSearchArg *args,
-			 MailSortType *sorting, OBuffer *outbuf, int uid_result)
+			 MailSortType *sorting, OStream *output, int uid_result)
 {
 	IndexMailbox *ibox = (IndexMailbox *) box;
 	MailSortContext *sort_ctx;
@@ -862,23 +862,23 @@
 
 	if (sorting == NULL) {
 		sort_ctx = NULL;
-		o_buffer_send(outbuf, "* SEARCH", 8);
+		o_stream_send(output, "* SEARCH", 8);
 	} else {
 		memset(&index_sort_ctx, 0, sizeof(index_sort_ctx));
 		index_sort_ctx.ibox = ibox;
-		index_sort_ctx.outbuf = outbuf;
+		index_sort_ctx.output = output;
 
 		sort_ctx = mail_sort_init(sort_unsorted, sorting,
 					  index_sort_funcs, &index_sort_ctx);
-		o_buffer_send(outbuf, "* SORT", 6);
+		o_stream_send(output, "* SORT", 6);
 	}
 
 	failed = !search_messages(ibox, charset, args, sort_ctx,
-				  outbuf, uid_result);
+				  output, uid_result);
 	if (sort_ctx != NULL)
 		mail_sort_deinit(sort_ctx);
 
-	o_buffer_send(outbuf, "\r\n", 2);
+	o_stream_send(output, "\r\n", 2);
 
 	if (!index_storage_lock(ibox, MAIL_LOCK_UNLOCK))
 		return FALSE;
--- a/src/lib-storage/index/index-sort.c	Fri Dec 06 00:37:33 2002 +0200
+++ b/src/lib-storage/index/index-sort.c	Fri Dec 06 03:09:22 2002 +0200
@@ -1,7 +1,7 @@
 /* Copyright (C) 2002 Timo Sirainen */
 
 #include "lib.h"
-#include "obuffer.h"
+#include "ostream.h"
 #include "rfc822-date.h"
 #include "imap-envelope.h"
 #include "imap-message-cache.h"
@@ -124,7 +124,7 @@
 
 	for (i = 0; i < count; i++) {
 		len = i_snprintf(num, sizeof(num), " %u", data[i]);
-		o_buffer_send(ctx->outbuf, num, len);
+		o_stream_send(ctx->output, num, len);
 	}
 }
 
--- a/src/lib-storage/index/index-sort.h	Fri Dec 06 00:37:33 2002 +0200
+++ b/src/lib-storage/index/index-sort.h	Fri Dec 06 03:09:22 2002 +0200
@@ -6,7 +6,7 @@
 
 typedef struct {
 	IndexMailbox *ibox;
-	OBuffer *outbuf;
+	OStream *output;
 
 	unsigned int last_uid;
 	MailIndexRecord *rec;
--- a/src/lib-storage/index/index-storage.h	Fri Dec 06 00:37:33 2002 +0200
+++ b/src/lib-storage/index/index-storage.h	Fri Dec 06 03:09:22 2002 +0200
@@ -59,7 +59,7 @@
 		       unsigned int seq, int notify);
 
 int index_storage_save(MailStorage *storage, const char *path,
-		       IBuffer *inbuf, OBuffer *outbuf, uoff_t data_size);
+		       IStream *input, OStream *output, uoff_t data_size);
 
 int index_msgcache_open(ImapMessageCache *cache, MailIndex *index,
 			MailIndexRecord *rec, ImapCacheField fields);
@@ -82,9 +82,9 @@
 			       ModifyType modify_type, int notify,
 			       int *all_found);
 int index_storage_fetch(Mailbox *box, MailFetchData *fetch_data,
-			OBuffer *outbuf, int *all_found);
+			OStream *output, int *all_found);
 int index_storage_search(Mailbox *box, const char *charset, MailSearchArg *args,
-			 MailSortType *sorting, OBuffer *outbuf,
+			 MailSortType *sorting, OStream *output,
 			 int uid_result);
 
 #endif
--- a/src/lib-storage/index/maildir/maildir-save.c	Fri Dec 06 00:37:33 2002 +0200
+++ b/src/lib-storage/index/maildir/maildir-save.c	Fri Dec 06 03:09:22 2002 +0200
@@ -3,7 +3,7 @@
 #include "lib.h"
 #include "ioloop.h"
 #include "hostpid.h"
-#include "obuffer.h"
+#include "ostream.h"
 #include "maildir-index.h"
 #include "maildir-storage.h"
 
@@ -48,10 +48,10 @@
 }
 
 static const char *maildir_read_into_tmp(MailStorage *storage, const char *dir,
-					 IBuffer *buf, uoff_t data_size)
+					 IStream *input, uoff_t data_size)
 {
 	const char *fname, *path;
-	OBuffer *outbuf;
+	OStream *output;
 	int fd;
 
 	fd = maildir_create_tmp(storage, dir, &fname);
@@ -59,15 +59,15 @@
 		return NULL;
 
 	t_push();
-	outbuf = o_buffer_create_file(fd, data_stack_pool, 4096,
+	output = o_stream_create_file(fd, data_stack_pool, 4096,
 				      IO_PRIORITY_DEFAULT, FALSE);
-	o_buffer_set_blocking(outbuf, 60000, NULL, NULL);
+	o_stream_set_blocking(output, 60000, NULL, NULL);
 
 	path = t_strconcat(dir, "/", fname, NULL);
-	if (!index_storage_save(storage, path, buf, outbuf, data_size))
+	if (!index_storage_save(storage, path, input, output, data_size))
 		fname = NULL;
 
-	o_buffer_unref(outbuf);
+	o_stream_unref(output);
 	if (close(fd) < 0)
 		fname = NULL;
 
@@ -80,7 +80,7 @@
 int maildir_storage_save(Mailbox *box, MailFlags flags,
 			 const char *custom_flags[], time_t internal_date,
 			 int timezone_offset __attr_unused__,
-			 IBuffer *data, uoff_t data_size)
+			 IStream *data, uoff_t data_size)
 {
         IndexMailbox *ibox = (IndexMailbox *) box;
         struct utimbuf buf;
--- a/src/lib-storage/index/maildir/maildir-storage.h	Fri Dec 06 00:37:33 2002 +0200
+++ b/src/lib-storage/index/maildir/maildir-storage.h	Fri Dec 06 03:09:22 2002 +0200
@@ -8,7 +8,7 @@
 int maildir_storage_save(Mailbox *box, MailFlags flags,
 			 const char *custom_flags[],
 			 time_t internal_date, int timezone_offset,
-			 IBuffer *data, uoff_t data_size);
+			 IStream *data, uoff_t data_size);
 
 int maildir_find_mailboxes(MailStorage *storage, const char *mask,
 			   MailboxFunc func, void *context);
--- a/src/lib-storage/index/mbox/mbox-expunge.c	Fri Dec 06 00:37:33 2002 +0200
+++ b/src/lib-storage/index/mbox/mbox-expunge.c	Fri Dec 06 03:09:22 2002 +0200
@@ -1,8 +1,8 @@
 /* Copyright (C) 2002 Timo Sirainen */
 
 #include "lib.h"
-#include "ibuffer.h"
-#include "obuffer.h"
+#include "istream.h"
+#include "ostream.h"
 #include "mbox-index.h"
 #include "mbox-storage.h"
 #include "mbox-lock.h"
@@ -11,7 +11,7 @@
 #include <unistd.h>
 
 static int expunge_real(IndexMailbox *ibox, MailIndexRecord *rec,
-			unsigned int seq, IBuffer *inbuf, OBuffer *outbuf,
+			unsigned int seq, IStream *input, OStream *output,
 			int notify)
 {
 	uoff_t offset, hdr_size, body_size;
@@ -36,7 +36,7 @@
 		rec = ibox->index->next(ibox->index, rec);
 	}
 
-	old_limit = inbuf->v_limit;
+	old_limit = input->v_limit;
 
 	expunges = FALSE;
 	while (rec != NULL) {
@@ -55,33 +55,33 @@
 			if (!expunges) {
 				/* first expunged record, seek to position
 				   where we want to begin writing */
-				if (!o_buffer_seek(outbuf, from_offset))
+				if (!o_stream_seek(output, from_offset))
 					return FALSE;
 				expunges = TRUE;
 			}
 		} else if (expunges) {
 			/* seek to wanted input position, and copy
 			   this messages */
-			i_assert(inbuf->v_offset <= from_offset);
-			i_buffer_skip(inbuf, from_offset - inbuf->v_offset);
+			i_assert(input->v_offset <= from_offset);
+			i_stream_skip(input, from_offset - input->v_offset);
 
-			if (outbuf->offset == 0) {
+			if (output->offset == 0) {
 				/* we're writing to beginning of mbox, so we
 				   don't want the [\r]\n there */
-				(void)i_buffer_read_data(inbuf, &data,
+				(void)i_stream_read_data(input, &data,
 							 &size, 1);
 				if (size > 0 && data[0] == '\n')
-					i_buffer_skip(inbuf, 1);
+					i_stream_skip(input, 1);
 				else if (size > 1 && data[0] == '\r' &&
 					 data[1] == '\n')
-					i_buffer_skip(inbuf, 2);
+					i_stream_skip(input, 2);
 			}
 
-			i_buffer_set_read_limit(inbuf, end_offset);
-			failed = o_buffer_send_ibuffer(outbuf, inbuf) < 0;
-			i_buffer_set_read_limit(inbuf, old_limit);
+			i_stream_set_read_limit(input, end_offset);
+			failed = o_stream_send_istream(output, input) < 0;
+			i_stream_set_read_limit(input, old_limit);
 
-			if (failed || inbuf->v_offset != end_offset)
+			if (failed || input->v_offset != end_offset)
 				return FALSE;
 		}
 
@@ -89,23 +89,23 @@
 		seq++;
 	}
 
-	i_buffer_skip(inbuf, end_offset - inbuf->v_offset);
+	i_stream_skip(input, end_offset - input->v_offset);
 
 	/* copy the rest as well, should be only \n but someone might
 	   as well just appended more data.. but if we've deleted all mail,
 	   don't write the only \n there. */
-	copy_size = inbuf->v_size - inbuf->v_offset;
-	if (outbuf->offset == 0 && copy_size == 1)
+	copy_size = input->v_size - input->v_offset;
+	if (output->offset == 0 && copy_size == 1)
 		return TRUE;
 
-	return o_buffer_send_ibuffer(outbuf, inbuf) >= 0;
+	return o_stream_send_istream(output, input) >= 0;
 }
 
 int mbox_expunge_locked(IndexMailbox *ibox, int notify)
 {
 	MailIndexRecord *rec;
-	IBuffer *inbuf;
-	OBuffer *outbuf;
+	IStream *input;
+	OStream *output;
 	unsigned int seq;
 	int failed;
 
@@ -118,35 +118,35 @@
 	}
 
 	/* mbox must be already opened, synced and locked at this point.
-	   we just want the IBuffer. */
-	inbuf = mbox_get_inbuf(ibox->index, 0, MAIL_LOCK_EXCLUSIVE);
-	if (inbuf == NULL)
+	   we just want the IStream. */
+	input = mbox_get_stream(ibox->index, 0, MAIL_LOCK_EXCLUSIVE);
+	if (input == NULL)
 		return FALSE;
 
 	i_assert(ibox->index->mbox_sync_counter ==
 		 ibox->index->mbox_lock_counter);
 
 	t_push();
-	outbuf = o_buffer_create_file(ibox->index->mbox_fd, data_stack_pool,
+	output = o_stream_create_file(ibox->index->mbox_fd, data_stack_pool,
 				      4096, 0, FALSE);
-	o_buffer_set_blocking(outbuf, 60000, NULL, NULL);
+	o_stream_set_blocking(output, 60000, NULL, NULL);
 
-	failed = !expunge_real(ibox, rec, seq, inbuf, outbuf, notify);
+	failed = !expunge_real(ibox, rec, seq, input, output, notify);
 
-	if (failed && outbuf->offset > 0) {
+	if (failed && output->offset > 0) {
 		/* we moved some of the data. move the rest as well so there
 		   won't be invalid holes in mbox file */
-		(void)o_buffer_send_ibuffer(outbuf, inbuf);
+		(void)o_stream_send_istream(output, input);
 	}
 
-	if (ftruncate(ibox->index->mbox_fd, (off_t)outbuf->offset) < 0) {
+	if (ftruncate(ibox->index->mbox_fd, (off_t)output->offset) < 0) {
 		mail_storage_set_error(ibox->box.storage, "ftruncate() failed "
 				       "for mbox file %s: %m",
 				       ibox->index->mbox_path);
 		failed = TRUE;
 	}
 
-	o_buffer_unref(outbuf);
+	o_stream_unref(output);
 	t_pop();
 
 	return !failed;
--- a/src/lib-storage/index/mbox/mbox-save.c	Fri Dec 06 00:37:33 2002 +0200
+++ b/src/lib-storage/index/mbox/mbox-save.c	Fri Dec 06 03:09:22 2002 +0200
@@ -2,7 +2,7 @@
 
 #include "lib.h"
 #include "hostpid.h"
-#include "obuffer.h"
+#include "ostream.h"
 #include "write-full.h"
 #include "mbox-index.h"
 #include "mbox-lock.h"
@@ -65,16 +65,16 @@
 	return TRUE;
 }
 
-static int mbox_append_lf(MailStorage *storage, OBuffer *outbuf,
+static int mbox_append_lf(MailStorage *storage, OStream *output,
 			  const char *mbox_path)
 {
-	if (o_buffer_send(outbuf, "\n", 1) < 0)
+	if (o_stream_send(output, "\n", 1) < 0)
 		return write_error(storage, mbox_path);
 
 	return TRUE;
 }
 
-static int write_from_line(MailStorage *storage, OBuffer *outbuf,
+static int write_from_line(MailStorage *storage, OStream *output,
 			   const char *mbox_path, time_t internal_date)
 {
 	const char *sender, *line, *name;
@@ -102,13 +102,13 @@
 	line = mbox_from_create(sender, internal_date);
 	len = strlen(line);
 
-	if (o_buffer_send(outbuf, line, len) < 0)
+	if (o_stream_send(output, line, len) < 0)
 		return write_error(storage, mbox_path);
 
 	return TRUE;
 }
 
-static int write_flags(MailStorage *storage, OBuffer *outbuf,
+static int write_flags(MailStorage *storage, OStream *output,
 		       const char *mbox_path,
 		       MailFlags flags, const char *custom_flags[])
 {
@@ -120,7 +120,7 @@
 		return TRUE;
 
 	if (flags & MAIL_SEEN) {
-		if (o_buffer_send(outbuf, "Status: R\n", 10) < 0)
+		if (o_stream_send(output, "Status: R\n", 10) < 0)
 			return write_error(storage, mbox_path);
 	}
 
@@ -132,27 +132,27 @@
 				  (flags & MAIL_DELETED) ? "T" : "",
 				  "\n", NULL);
 
-		if (o_buffer_send(outbuf, str, strlen(str)) < 0)
+		if (o_stream_send(output, str, strlen(str)) < 0)
 			return write_error(storage, mbox_path);
 	}
 
 	if (flags & MAIL_CUSTOM_FLAGS_MASK) {
-		if (o_buffer_send(outbuf, "X-Keywords:", 11) < 0)
+		if (o_stream_send(output, "X-Keywords:", 11) < 0)
 			return write_error(storage, mbox_path);
 
 		field = 1 << MAIL_CUSTOM_FLAG_1_BIT;
 		for (i = 0; i < MAIL_CUSTOM_FLAGS_COUNT; i++, field <<= 1) {
 			if ((flags & field) && custom_flags[i] != NULL) {
-				if (o_buffer_send(outbuf, " ", 1) < 0)
+				if (o_stream_send(output, " ", 1) < 0)
 					return write_error(storage, mbox_path);
 
-				if (o_buffer_send(outbuf, custom_flags[i],
+				if (o_stream_send(output, custom_flags[i],
 						  strlen(custom_flags[i])) < 0)
 					return write_error(storage, mbox_path);
 			}
 		}
 
-		if (o_buffer_send(outbuf, "\n", 1) < 0)
+		if (o_stream_send(output, "\n", 1) < 0)
 			return write_error(storage, mbox_path);
 	}
 
@@ -161,13 +161,13 @@
 
 int mbox_storage_save(Mailbox *box, MailFlags flags, const char *custom_flags[],
 		      time_t internal_date, int timezone_offset __attr_unused__,
-		      IBuffer *data, uoff_t data_size)
+		      IStream *data, uoff_t data_size)
 {
 	IndexMailbox *ibox = (IndexMailbox *) box;
 	MailIndex *index;
 	MailFlags real_flags;
 	const char *mbox_path;
-	OBuffer *outbuf;
+	OStream *output;
 	int failed;
 	off_t pos;
 
@@ -193,26 +193,26 @@
 		failed = FALSE;
 
 		t_push();
-		outbuf = o_buffer_create_file(index->mbox_fd,
+		output = o_stream_create_file(index->mbox_fd,
 					      data_stack_pool, 4096,
 					      0, FALSE);
-		o_buffer_set_blocking(outbuf, 60000, NULL, NULL);
+		o_stream_set_blocking(output, 60000, NULL, NULL);
 
-		if (!write_from_line(box->storage, outbuf, mbox_path,
+		if (!write_from_line(box->storage, output, mbox_path,
 				     internal_date) ||
-		    !write_flags(box->storage, outbuf, mbox_path, flags,
+		    !write_flags(box->storage, output, mbox_path, flags,
 				 custom_flags) ||
 		    !index_storage_save(box->storage, mbox_path,
-					data, outbuf, data_size) ||
-		    !mbox_append_lf(box->storage, outbuf, mbox_path)) {
+					data, output, data_size) ||
+		    !mbox_append_lf(box->storage, output, mbox_path)) {
 			/* failed, truncate file back to original size.
-			   output buffer needs to be flushed before truncating
+			   output stream needs to be flushed before truncating
 			   so unref() won't write anything. */
-			o_buffer_flush(outbuf);
+			o_stream_flush(output);
 			(void)ftruncate(index->mbox_fd, pos);
 			failed = TRUE;
 		}
-		o_buffer_unref(outbuf);
+		o_stream_unref(output);
 		t_pop();
 	}
 
--- a/src/lib-storage/index/mbox/mbox-storage.h	Fri Dec 06 00:37:33 2002 +0200
+++ b/src/lib-storage/index/mbox/mbox-storage.h	Fri Dec 06 03:09:22 2002 +0200
@@ -7,7 +7,7 @@
 		      const char *messageset, int uidset);
 int mbox_storage_save(Mailbox *box, MailFlags flags, const char *custom_flags[],
 		      time_t internal_date, int timezone_offset,
-		      IBuffer *data, uoff_t data_size);
+		      IStream *data, uoff_t data_size);
 
 int mbox_find_mailboxes(MailStorage *storage, const char *mask,
 			MailboxFunc func, void *context);
--- a/src/lib-storage/mail-sort.c	Fri Dec 06 00:37:33 2002 +0200
+++ b/src/lib-storage/mail-sort.c	Fri Dec 06 03:09:22 2002 +0200
@@ -1,7 +1,7 @@
 /* Copyright (C) 2002 Timo Sirainen */
 
 #include "lib.h"
-#include "obuffer.h"
+#include "ostream.h"
 #include "mail-sort.h"
 
 #include <stdlib.h>
--- a/src/lib-storage/mail-storage.h	Fri Dec 06 00:37:33 2002 +0200
+++ b/src/lib-storage/mail-storage.h	Fri Dec 06 03:09:22 2002 +0200
@@ -152,24 +152,24 @@
 	int (*copy)(Mailbox *box, Mailbox *destbox,
 		    const char *messageset, int uidset);
 
-	/* Fetch wanted mail data. The results are written into outbuf
+	/* Fetch wanted mail data. The results are written into output stream
 	   in RFC2060 FETCH format. */
 	int (*fetch)(Mailbox *box, MailFetchData *fetch_data,
-		     OBuffer *outbuf, int *all_found);
+		     OStream *output, int *all_found);
 
 	/* Search wanted mail data. args contains the search criteria.
-	   Results are written into outbuf in RFC2060 SEARCH format.
+	   Results are written into output stream in RFC2060 SEARCH format.
 	   If charset is NULL, the given search strings are matched without
 	   any conversion. */
 	int (*search)(Mailbox *box, const char *charset, MailSearchArg *args,
-		      MailSortType *sorting, OBuffer *outbuf, int uid_result);
+		      MailSortType *sorting, OStream *output, int uid_result);
 
 	/* Save a new mail into mailbox. timezone_offset specifies the
 	   timezone in minutes which internal_date was originally given
 	   with. */
 	int (*save)(Mailbox *box, MailFlags flags, const char *custom_flags[],
 		    time_t internal_date, int timezone_offset,
-		    IBuffer *data, uoff_t data_size);
+		    IStream *data, uoff_t data_size);
 
 	/* Returns TRUE if mailbox is now in inconsistent state, meaning that
 	   the message IDs etc. may have changed - only way to recover this
--- a/src/lib/Makefile.am	Fri Dec 06 00:37:33 2002 +0200
+++ b/src/lib/Makefile.am	Fri Dec 06 03:09:22 2002 +0200
@@ -15,11 +15,11 @@
 	hex-binary.c \
 	hostpid.c \
 	imem.c \
-	iobuffer.c \
-	ibuffer.c \
-	ibuffer-data.c \
-	ibuffer-file.c \
-	ibuffer-mmap.c \
+	iostream.c \
+	istream.c \
+	istream-data.c \
+	istream-file.c \
+	istream-mmap.c \
 	ioloop.c \
 	ioloop-poll.c \
 	ioloop-select.c \
@@ -33,8 +33,8 @@
 	mmap-anon.c \
 	mmap-util.c \
 	network.c \
-	obuffer.c \
-	obuffer-file.c \
+	ostream.c \
+	ostream-file.c \
 	primes.c \
 	process-title.c \
 	randgen.c \
@@ -64,9 +64,9 @@
 	hex-binary.h \
 	hostpid.h \
 	imem.h \
-	iobuffer-internal.h \
-	ibuffer.h \
-	ibuffer-internal.h \
+	iostream-internal.h \
+	istream.h \
+	istream-internal.h \
 	ioloop.h \
 	ioloop-internal.h \
 	lib.h \
@@ -76,8 +76,8 @@
 	mempool.h \
 	mmap-util.h \
 	network.h \
-	obuffer.h \
-	obuffer-internal.h \
+	ostream.h \
+	ostream-internal.h \
 	primes.h \
 	process-title.h \
 	randgen.h \
--- a/src/lib/ibuffer-data.c	Fri Dec 06 00:37:33 2002 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,85 +0,0 @@
-/*
-   ibuffer-data.c : Input buffer interface for reading from data buffer
-
-    Copyright (c) 2002 Timo Sirainen
-
-    Permission is hereby granted, free of charge, to any person obtaining
-    a copy of this software and associated documentation files (the
-    "Software"), to deal in the Software without restriction, including
-    without limitation the rights to use, copy, modify, merge, publish,
-    distribute, sublicense, and/or sell copies of the Software, and to
-    permit persons to whom the Software is furnished to do so, subject to
-    the following conditions:
-
-    The above copyright notice and this permission notice shall be
-    included in all copies or substantial portions of the Software.
-
-    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-    TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-    SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-*/
-
-#include "lib.h"
-#include "ibuffer-internal.h"
-
-static void _close(_IOBuffer *buf __attr_unused__)
-{
-}
-
-static void _destroy(_IOBuffer *buf __attr_unused__)
-{
-}
-
-static void _set_max_size(_IOBuffer *buf __attr_unused__,
-			  size_t max_size __attr_unused__)
-{
-}
-
-static void _set_blocking(_IOBuffer *buf __attr_unused__,
-			  int timeout_msecs __attr_unused__,
-			  void (*timeout_func)(void *) __attr_unused__,
-			  void *context __attr_unused__)
-{
-}
-
-static ssize_t _read(_IBuffer *buf)
-{
-	return buf->pos - buf->skip;
-}
-
-static void _seek(_IBuffer *buf, uoff_t v_offset)
-{
-	buf->skip = v_offset;
-	buf->ibuffer.v_offset = v_offset;
-}
-
-static void _skip(_IBuffer *buf, uoff_t count)
-{
-	buf->skip += count;
-	buf->ibuffer.v_offset += count;
-}
-
-IBuffer *i_buffer_create_from_data(Pool pool, const unsigned char *data,
-				   size_t size)
-{
-	_IBuffer *buf;
-
-	buf = p_new(pool, _IBuffer, 1);
-	buf->buffer = data;
-	buf->pos = size;
-
-	buf->iobuf.close = _close;
-	buf->iobuf.destroy = _destroy;
-	buf->iobuf.set_max_size = _set_max_size;
-	buf->iobuf.set_blocking = _set_blocking;
-
-	buf->read = _read;
-	buf->skip_count = _skip;
-	buf->seek = _seek;
-
-	return _i_buffer_create(buf, pool, -1, 0, size);
-}
--- a/src/lib/ibuffer-file.c	Fri Dec 06 00:37:33 2002 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,290 +0,0 @@
-/*
-   ibuffer-file.c : Input buffer handling for files
-
-    Copyright (c) 2002 Timo Sirainen
-
-    Permission is hereby granted, free of charge, to any person obtaining
-    a copy of this software and associated documentation files (the
-    "Software"), to deal in the Software without restriction, including
-    without limitation the rights to use, copy, modify, merge, publish,
-    distribute, sublicense, and/or sell copies of the Software, and to
-    permit persons to whom the Software is furnished to do so, subject to
-    the following conditions:
-
-    The above copyright notice and this permission notice shall be
-    included in all copies or substantial portions of the Software.
-
-    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-    TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-    SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-*/
-
-#include "lib.h"
-#include "alarm-hup.h"
-#include "ibuffer-internal.h"
-#include "network.h"
-
-#include <time.h>
-#include <unistd.h>
-#include <sys/stat.h>
-
-#define I_BUFFER_MIN_SIZE 4096
-
-#define BUFFER_IS_BLOCKING(fbuf) \
-	((fbuf)->timeout_msecs != 0)
-
-typedef struct {
-	_IBuffer ibuf;
-
-	size_t max_buffer_size;
-	uoff_t skip_left;
-
-	int timeout_msecs;
-	void (*timeout_func)(void *);
-	void *timeout_context;
-
-	unsigned int file:1;
-	unsigned int autoclose_fd:1;
-} FileIBuffer;
-
-static void _close(_IOBuffer *buf)
-{
-	FileIBuffer *fbuf = (FileIBuffer *) buf;
-	_IBuffer *_buf = (_IBuffer *) buf;
-
-	if (fbuf->autoclose_fd && _buf->fd != -1) {
-		if (close(_buf->fd) < 0)
-			i_error("FileIBuffer.close() failed: %m");
-		_buf->fd = -1;
-	}
-}
-
-static void _destroy(_IOBuffer *buf)
-{
-	_IBuffer *_buf = (_IBuffer *) buf;
-
-	p_free(_buf->iobuf.pool, _buf->w_buffer);
-}
-
-static void _set_max_size(_IOBuffer *buf, size_t max_size)
-{
-	FileIBuffer *fbuf = (FileIBuffer *) buf;
-
-	fbuf->max_buffer_size = max_size;
-}
-
-static void _set_blocking(_IOBuffer *buf, int timeout_msecs,
-			  void (*timeout_func)(void *), void *context)
-{
-	FileIBuffer *fbuf = (FileIBuffer *) buf;
-
-	fbuf->timeout_msecs = timeout_msecs;
-	fbuf->timeout_func = timeout_func;
-	fbuf->timeout_context = context;
-
-	net_set_nonblock(fbuf->ibuf.fd, timeout_msecs == 0);
-
-	if (timeout_msecs != 0)
-		alarm_hup_init();
-}
-
-static void i_buffer_grow(_IBuffer *buf, size_t bytes)
-{
-	FileIBuffer *fbuf = (FileIBuffer *) buf;
-
-	buf->buffer_size = buf->pos + bytes;
-	buf->buffer_size =
-		buf->buffer_size <= I_BUFFER_MIN_SIZE ? I_BUFFER_MIN_SIZE :
-		nearest_power(buf->buffer_size);
-
-	if (fbuf->max_buffer_size > 0 &&
-	    buf->buffer_size > fbuf->max_buffer_size)
-		buf->buffer_size = fbuf->max_buffer_size;
-
-	buf->buffer = buf->w_buffer =
-		p_realloc(buf->iobuf.pool, buf->w_buffer, buf->buffer_size);
-}
-
-static void i_buffer_compress(_IBuffer *buf)
-{
-	memmove(buf->w_buffer, buf->w_buffer + buf->skip, buf->pos - buf->skip);
-	buf->pos -= buf->skip;
-
-	if (buf->skip > buf->cr_lookup_pos)
-		buf->cr_lookup_pos = 0;
-	else
-		buf->cr_lookup_pos -= buf->skip;
-
-	buf->skip = 0;
-}
-
-static ssize_t _read(_IBuffer *buf)
-{
-	FileIBuffer *fbuf = (FileIBuffer *) buf;
-	time_t timeout_time;
-	uoff_t read_limit;
-	size_t size;
-	ssize_t ret;
-
-	if (buf->ibuffer.closed)
-		return -1;
-
-	if (fbuf->skip_left > 0) {
-		i_assert(buf->skip == buf->pos);
-
-		if (fbuf->file) {
-			/* we're a file, so we can lseek() */
-			i_buffer_seek(&buf->ibuffer, buf->ibuffer.v_offset);
-			if (buf->ibuffer.closed)
-				return -1;
-		}
-	}
-
-	buf->ibuffer.buf_errno = 0;
-
-	if (buf->pos == buf->buffer_size) {
-		if (buf->skip > 0) {
-			/* remove the unused bytes from beginning of buffer */
-                        i_buffer_compress(buf);
-		} else if (fbuf->max_buffer_size == 0 ||
-			   buf->buffer_size < fbuf->max_buffer_size) {
-			/* buffer is full - grow it */
-			i_buffer_grow(buf, I_BUFFER_MIN_SIZE);
-		}
-
-		if (buf->pos == buf->buffer_size)
-			return -2; /* buffer full */
-	}
-
-	size = buf->buffer_size - buf->pos;
-	if (buf->ibuffer.v_limit > 0) {
-		i_assert(buf->ibuffer.v_limit >= buf->ibuffer.v_offset);
-
-		read_limit = buf->ibuffer.v_limit -
-			buf->ibuffer.v_offset + fbuf->skip_left;
-		if (read_limit <= buf->pos - buf->skip) {
-			/* virtual limit reached == EOF */
-			return -1;
-		}
-
-		read_limit -= buf->pos - buf->skip;
-		if (size > read_limit)
-			size = read_limit;
-	}
-
-	timeout_time = GET_TIMEOUT_TIME(fbuf);
-
-	ret = -1;
-	do {
-		if (ret == 0 && timeout_time > 0 && time(NULL) > timeout_time) {
-			/* timeouted */
-			if (fbuf->timeout_func != NULL)
-				fbuf->timeout_func(fbuf->timeout_context);
-			buf->ibuffer.buf_errno = EAGAIN;
-			return -1;
-		}
-
-		ret = read(buf->fd, buf->w_buffer + buf->pos, size);
-		if (ret == 0) {
-			/* EOF */
-			buf->ibuffer.buf_errno = 0;
-			return -1;
-		}
-
-		if (ret < 0) {
-			if (errno == EINTR || errno == EAGAIN)
-				ret = 0;
-			else {
-				buf->ibuffer.buf_errno = errno;
-				return -1;
-			}
-		}
-
-		if (ret > 0 && fbuf->skip_left > 0) {
-			if (fbuf->skip_left >= (size_t)ret) {
-				fbuf->skip_left -= ret;
-				ret = 0;
-			} else {
-				ret -= fbuf->skip_left;
-				buf->pos += fbuf->skip_left;
-				buf->skip += fbuf->skip_left;
-				fbuf->skip_left = 0;
-			}
-		}
-	} while (ret == 0 && BUFFER_IS_BLOCKING(fbuf));
-
-	buf->pos += ret;
-	return ret;
-}
-
-static void _skip(_IBuffer *buf, uoff_t count)
-{
-	FileIBuffer *fbuf = (FileIBuffer *) buf;
-
-	fbuf->skip_left += count - (buf->pos - buf->skip);
-	buf->skip = buf->pos = 0;
-	buf->ibuffer.v_offset += count;
-}
-
-static void _seek(_IBuffer *buf, uoff_t v_offset)
-{
-	FileIBuffer *fbuf = (FileIBuffer *) buf;
-	uoff_t real_offset;
-	off_t ret;
-
-	real_offset = buf->ibuffer.start_offset + v_offset;
-	if (real_offset > OFF_T_MAX) {
-		buf->ibuffer.buf_errno = EOVERFLOW;
-		ret = -1;
-	} else {
-		ret = lseek(buf->fd, (off_t)real_offset, SEEK_SET);
-		if (ret < 0)
-			buf->ibuffer.buf_errno = errno;
-		else if (ret != (off_t)real_offset) {
-			buf->ibuffer.buf_errno = EINVAL;
-			ret = -1;
-		} else {
-			buf->skip = buf->pos = 0;
-			fbuf->skip_left = 0;
-		}
-	}
-
-	if (ret < 0)
-                i_buffer_close(&buf->ibuffer);
-	else {
-		buf->ibuffer.buf_errno = 0;
-		buf->ibuffer.v_offset = v_offset;
-	}
-}
-
-IBuffer *i_buffer_create_file(int fd, Pool pool, size_t max_buffer_size,
-			      int autoclose_fd)
-{
-	FileIBuffer *fbuf;
-	struct stat st;
-
-	fbuf = p_new(pool, FileIBuffer, 1);
-	fbuf->max_buffer_size = max_buffer_size;
-	fbuf->autoclose_fd = autoclose_fd;
-
-	fbuf->ibuf.iobuf.close = _close;
-	fbuf->ibuf.iobuf.destroy = _destroy;
-	fbuf->ibuf.iobuf.set_max_size = _set_max_size;
-	fbuf->ibuf.iobuf.set_blocking = _set_blocking;
-
-	fbuf->ibuf.read = _read;
-	fbuf->ibuf.skip_count = _skip;
-	fbuf->ibuf.seek = _seek;
-
-	/* get size of fd if it's a file */
-	if (fstat(fd, &st) < 0)
-		st.st_size = 0;
-	else if (S_ISREG(st.st_mode))
-		fbuf->file = TRUE;
-
-	return _i_buffer_create(&fbuf->ibuf, pool, fd, 0, (uoff_t)st.st_size);
-}
--- a/src/lib/ibuffer-internal.h	Fri Dec 06 00:37:33 2002 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +0,0 @@
-#ifndef __IBUFFER_INTERNAL_H
-#define __IBUFFER_INTERNAL_H
-
-#include "ibuffer.h"
-#include "iobuffer-internal.h"
-
-typedef struct __IBuffer _IBuffer;
-
-struct __IBuffer {
-/* inheritance: */
-	_IOBuffer iobuf;
-
-/* methods: */
-	ssize_t (*read)(_IBuffer *buf);
-	void (*skip_count)(_IBuffer *buf, uoff_t count);
-	void (*seek)(_IBuffer *buf, uoff_t v_offset);
-
-/* data: */
-	IBuffer ibuffer;
-
-	int fd;
-	const unsigned char *buffer;
-	unsigned char *w_buffer; /* may be NULL */
-	size_t buffer_size;
-
-	size_t skip, pos, cr_lookup_pos;
-};
-
-IBuffer *_i_buffer_create(_IBuffer *_buf, Pool pool, int fd,
-			  uoff_t start_offset, uoff_t v_size);
-
-#endif
--- a/src/lib/ibuffer-mmap.c	Fri Dec 06 00:37:33 2002 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,240 +0,0 @@
-/*
-   ibuffer-mmap.c : Input buffer handling for mmap()ed files
-
-    Copyright (c) 2002 Timo Sirainen
-
-    Permission is hereby granted, free of charge, to any person obtaining
-    a copy of this software and associated documentation files (the
-    "Software"), to deal in the Software without restriction, including
-    without limitation the rights to use, copy, modify, merge, publish,
-    distribute, sublicense, and/or sell copies of the Software, and to
-    permit persons to whom the Software is furnished to do so, subject to
-    the following conditions:
-
-    The above copyright notice and this permission notice shall be
-    included in all copies or substantial portions of the Software.
-
-    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-    TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-    SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-*/
-
-#include "lib.h"
-#include "mmap-util.h"
-#include "ibuffer-internal.h"
-
-#include <unistd.h>
-#include <sys/stat.h>
-
-typedef struct {
-	_IBuffer ibuf;
-
-	int fd;
-	void *mmap_base;
-	off_t mmap_offset;
-	size_t mmap_block_size;
-
-	unsigned int autoclose_fd:1;
-} MmapIBuffer;
-
-static size_t mmap_pagesize = 0;
-static size_t mmap_pagemask = 0;
-
-static void _close(_IOBuffer *buf)
-{
-	MmapIBuffer *mbuf = (MmapIBuffer *) buf;
-
-	if (mbuf->autoclose_fd && mbuf->fd != -1) {
-		if (close(mbuf->fd) < 0)
-			i_error("MmapIBuffer.close() failed: %m");
-		mbuf->fd = -1;
-	}
-}
-
-static void i_buffer_munmap(MmapIBuffer *mbuf)
-{
-	_IBuffer *_buf = &mbuf->ibuf;
-
-	if (_buf->buffer != NULL) {
-		if (munmap(mbuf->mmap_base, _buf->buffer_size) < 0)
-			i_error("MmapIBuffer.munmap() failed: %m");
-		mbuf->mmap_base = NULL;
-		_buf->buffer = NULL;
-		_buf->buffer_size = 0;
-		mbuf->mmap_offset = 0;
-	}
-}
-
-static void _destroy(_IOBuffer *buf)
-{
-	MmapIBuffer *mbuf = (MmapIBuffer *) buf;
-
-	i_buffer_munmap(mbuf);
-}
-
-static void _set_max_size(_IOBuffer *buf, size_t max_size)
-{
-	MmapIBuffer *mbuf = (MmapIBuffer *) buf;
-
-	mbuf->mmap_block_size = max_size;
-}
-
-static void _set_blocking(_IOBuffer *buf __attr_unused__,
-			  int timeout_msecs __attr_unused__,
-			  void (*timeout_func)(void *) __attr_unused__,
-			  void *context __attr_unused__)
-{
-	/* we never block */
-}
-
-static ssize_t io_buffer_set_mmaped_pos(_IBuffer *buf)
-{
-	MmapIBuffer *mbuf = (MmapIBuffer *) buf;
-
-	i_assert((uoff_t)mbuf->mmap_offset <=
-		 buf->ibuffer.start_offset + buf->ibuffer.v_limit);
-
-	buf->pos = buf->ibuffer.start_offset + buf->ibuffer.v_limit -
-		mbuf->mmap_offset;
-	if (buf->pos > buf->buffer_size)
-		buf->pos = buf->buffer_size;
-
-	return buf->pos - buf->skip;
-}
-
-static ssize_t _read(_IBuffer *buf)
-{
-	MmapIBuffer *mbuf = (MmapIBuffer *) buf;
-	size_t aligned_skip, limit_size;
-
-	if (buf->ibuffer.start_offset + buf->ibuffer.v_limit <=
-	    (uoff_t)mbuf->mmap_offset + buf->pos) {
-		/* end of file */
-		buf->ibuffer.buf_errno = 0;
-		return -1;
-	}
-
-	if (buf->pos < buf->buffer_size) {
-		/* more bytes available without needing to mmap() */
-		return io_buffer_set_mmaped_pos(buf);
-	}
-
-	aligned_skip = buf->skip & ~mmap_pagemask;
-	if (aligned_skip == 0 && mbuf->mmap_base != NULL) {
-		/* didn't skip enough bytes */
-		return -2;
-	}
-
-	buf->skip -= aligned_skip;
-	mbuf->mmap_offset += aligned_skip;
-
-	if (mbuf->mmap_base != NULL) {
-		if (munmap(mbuf->mmap_base, buf->buffer_size) < 0)
-			i_error("io_buffer_read_mmaped(): munmap() failed: %m");
-	}
-
-	buf->buffer_size = buf->ibuffer.start_offset + buf->ibuffer.v_size -
-		mbuf->mmap_offset;
-	if (buf->buffer_size > mbuf->mmap_block_size)
-		buf->buffer_size = mbuf->mmap_block_size;
-
-	i_assert((uoff_t)mbuf->mmap_offset + buf->buffer_size <=
-		 buf->ibuffer.start_offset + buf->ibuffer.v_size);
-
-	mbuf->mmap_base = mmap(NULL, buf->buffer_size, PROT_READ, MAP_PRIVATE,
-			       mbuf->fd, mbuf->mmap_offset);
-	buf->buffer = mbuf->mmap_base;
-	if (mbuf->mmap_base == MAP_FAILED) {
-		buf->ibuffer.buf_errno = errno;
-		mbuf->mmap_base = NULL;
-		buf->buffer = NULL;
-		buf->buffer_size = 0;
-		buf->skip = buf->pos = 0;
-		i_error("MmapIBuffer.mmap() failed: %m");
-		return -1;
-	}
-
-	/* madvise() only if non-limited mmap()ed buffer area larger than
-	   page size */
-	limit_size = buf->ibuffer.start_offset + buf->ibuffer.v_limit -
-		mbuf->mmap_offset;
-	if (limit_size > mmap_pagesize) {
-		if (limit_size > buf->buffer_size)
-			limit_size = buf->buffer_size;
-
-		if (madvise(mbuf->mmap_base, limit_size, MADV_SEQUENTIAL) < 0)
-			i_error("MmapIBuffer.madvise(): %m");
-	}
-
-	return io_buffer_set_mmaped_pos(buf);
-}
-
-static void _seek(_IBuffer *buf, uoff_t v_offset)
-{
-	MmapIBuffer *mbuf = (MmapIBuffer *) buf;
-	uoff_t abs_offset;
-
-	abs_offset = buf->ibuffer.start_offset + v_offset;
-	if (buf->buffer_size != 0 &&
-	    (uoff_t)mbuf->mmap_offset <= abs_offset &&
-	    (uoff_t)mbuf->mmap_offset + buf->buffer_size > abs_offset) {
-		/* already mmaped */
-		buf->skip = buf->pos = abs_offset - mbuf->mmap_offset;
-	} else {
-		/* force reading next time */
-		i_buffer_munmap(mbuf);
-		buf->skip = buf->pos = abs_offset;
-	}
-
-	buf->ibuffer.v_offset = v_offset;
-}
-
-static void _skip(_IBuffer *buf, uoff_t count)
-{
-	_seek(buf, buf->ibuffer.v_offset + count);
-}
-
-IBuffer *i_buffer_create_mmap(int fd, Pool pool, size_t block_size,
-			      uoff_t start_offset, uoff_t v_size,
-			      int autoclose_fd)
-{
-	MmapIBuffer *mbuf;
-	struct stat st;
-
-	if (mmap_pagesize == 0) {
-		mmap_pagesize = getpagesize();
-		mmap_pagemask = mmap_pagesize-1;
-	}
-
-	if (v_size == 0) {
-		if (fstat(fd, &st) < 0) {
-			i_error("i_buffer_create_mmap(): fstat() failed: %m");
-			v_size = 0;
-		} else {
-			v_size = st.st_size;
-			if (start_offset > v_size)
-				start_offset = v_size;
-			v_size -= start_offset;
-		}
-	}
-
-	mbuf = p_new(pool, MmapIBuffer, 1);
-	mbuf->fd = fd;
-	mbuf->mmap_block_size = block_size;
-	mbuf->autoclose_fd = autoclose_fd;
-
-	mbuf->ibuf.iobuf.close = _close;
-	mbuf->ibuf.iobuf.destroy = _destroy;
-	mbuf->ibuf.iobuf.set_max_size = _set_max_size;
-	mbuf->ibuf.iobuf.set_blocking = _set_blocking;
-
-	mbuf->ibuf.read = _read;
-	mbuf->ibuf.skip_count = _skip;
-	mbuf->ibuf.seek = _seek;
-
-	return _i_buffer_create(&mbuf->ibuf, pool, fd, start_offset, v_size);
-}
--- a/src/lib/ibuffer.c	Fri Dec 06 00:37:33 2002 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,243 +0,0 @@
-/*
-   ibuffer.c : Input buffer handling
-
-    Copyright (c) 2002 Timo Sirainen
-
-    Permission is hereby granted, free of charge, to any person obtaining
-    a copy of this software and associated documentation files (the
-    "Software"), to deal in the Software without restriction, including
-    without limitation the rights to use, copy, modify, merge, publish,
-    distribute, sublicense, and/or sell copies of the Software, and to
-    permit persons to whom the Software is furnished to do so, subject to
-    the following conditions:
-
-    The above copyright notice and this permission notice shall be
-    included in all copies or substantial portions of the Software.
-
-    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-    TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-    SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-*/
-
-#include "lib.h"
-#include "ibuffer-internal.h"
-
-void i_buffer_ref(IBuffer *buf)
-{
-	_io_buffer_ref(buf->real_buffer);
-}
-
-void i_buffer_unref(IBuffer *buf)
-{
-	_io_buffer_unref(buf->real_buffer);
-}
-
-int i_buffer_get_fd(IBuffer *buf)
-{
-	_IBuffer *_buf = buf->real_buffer;
-
-	return _buf->fd;
-}
-
-void i_buffer_close(IBuffer *buf)
-{
-	_io_buffer_close(buf->real_buffer);
-	buf->closed = TRUE;
-}
-
-void i_buffer_set_max_size(IBuffer *buf, size_t max_size)
-{
-	_io_buffer_set_max_size(buf->real_buffer, max_size);
-}
-
-void i_buffer_set_blocking(IBuffer *buf, int timeout_msecs,
-			   void (*timeout_func)(void *), void *context)
-{
-	_io_buffer_set_blocking(buf->real_buffer, timeout_msecs,
-				timeout_func, context);
-}
-
-void i_buffer_set_start_offset(IBuffer *buf, uoff_t offset)
-{
-	_IBuffer *_buf = buf->real_buffer;
-	off_t diff;
-
-	i_assert(buf->v_size == 0 || offset <= buf->start_offset + buf->v_size);
-
-	if (offset == buf->start_offset)
-		return;
-
-	diff = (off_t)buf->start_offset - (off_t)offset;
-	buf->start_offset = offset;
-	buf->v_offset += diff;
-	if (buf->v_size != 0) {
-		buf->v_size += diff;
-		buf->v_limit += diff;
-	}
-
-	/* reset buffer data */
-	_buf->skip = _buf->pos = _buf->cr_lookup_pos = 0;
-}
-
-void i_buffer_set_read_limit(IBuffer *buf, uoff_t v_offset)
-{
-	_IBuffer *_buf = buf->real_buffer;
-
-	i_assert(buf->v_size == 0 || v_offset <= buf->v_size);
-
-	if (v_offset == 0)
-		buf->v_limit = buf->v_size;
-	else {
-		i_assert(v_offset >= buf->v_offset);
-
-		buf->v_limit = v_offset;
-		if (_buf->pos > v_offset - buf->v_offset + _buf->skip)
-			_buf->pos = v_offset - buf->v_offset + _buf->skip;
-	}
-}
-
-ssize_t i_buffer_read(IBuffer *buf)
-{
-	_IBuffer *_buf = buf->real_buffer;
-
-	if (buf->closed)
-		return -1;
-
-	return _buf->read(_buf);
-}
-
-void i_buffer_skip(IBuffer *buf, uoff_t count)
-{
-	_IBuffer *_buf = buf->real_buffer;
-	size_t data_size;
-
-	i_assert(buf->v_size == 0 || buf->v_offset + count <= buf->v_size);
-
-	if (count <= _buf->pos - _buf->skip) {
-		buf->v_offset += count;
-		_buf->skip += count;
-		return;
-	}
-
-	if (buf->closed)
-		return;
-
-	data_size = _buf->pos - _buf->skip;
-	_buf->skip = _buf->pos;
-
-	count -= data_size;
-	buf->v_offset += data_size;
-
-	_buf->skip_count(_buf, count);
-}
-
-void i_buffer_seek(IBuffer *buf, uoff_t v_offset)
-{
-	_IBuffer *_buf = buf->real_buffer;
-
-	i_assert(v_offset <= buf->v_size);
-
-	if (buf->closed)
-		return;
-
-	_buf->seek(_buf, v_offset);
-}
-
-char *i_buffer_next_line(IBuffer *buf)
-{
-	_IBuffer *_buf = buf->real_buffer;
-	char *ret_buf;
-        size_t i;
-
-        i_assert(buf != NULL);
-
-	if (_buf->skip >= _buf->pos)
-		return NULL;
-
-	if (_buf->w_buffer == NULL) {
-		i_error("i_buffer_next_line() called for unmodifyable buffer");
-		return NULL;
-	}
-
-	ret_buf = NULL;
-	for (i = _buf->cr_lookup_pos; i < _buf->pos; i++) {
-		if (_buf->buffer[i] == 10) {
-			/* got it */
-			if (i > 0 && _buf->buffer[i-1] == '\r')
-				_buf->w_buffer[i-1] = '\0';
-			else
-				_buf->w_buffer[i] = '\0';
-			ret_buf = (char *) _buf->w_buffer + _buf->skip;
-
-			i++;
-			buf->v_offset += i - _buf->skip;
-			_buf->skip = i;
-                        break;
-		}
-	}
-
-	_buf->cr_lookup_pos = i;
-        return ret_buf;
-}
-
-const unsigned char *i_buffer_get_data(IBuffer *buf, size_t *size)
-{
-	_IBuffer *_buf = buf->real_buffer;
-
-	if (_buf->skip >= _buf->pos) {
-		*size = 0;
-		return NULL;
-	}
-
-        *size = _buf->pos - _buf->skip;
-        return _buf->buffer + _buf->skip;
-}
-
-unsigned char *i_buffer_get_modifyable_data(IBuffer *buf, size_t *size)
-{
-	_IBuffer *_buf = buf->real_buffer;
-
-	if (_buf->skip >= _buf->pos || _buf->w_buffer == NULL) {
-		*size = 0;
-		return NULL;
-	}
-
-        *size = _buf->pos - _buf->skip;
-        return _buf->w_buffer + _buf->skip;
-}
-
-int i_buffer_read_data(IBuffer *buf, const unsigned char **data,
-		       size_t *size, size_t threshold)
-{
-	_IBuffer *_buf = buf->real_buffer;
-	ssize_t ret = 0;
-
-	while (_buf->pos - _buf->skip <= threshold) {
-		/* we need more data */
-		ret = _buf->read(_buf);
-		if (ret < 0)
-			break;
-	}
-
-	*data = i_buffer_get_data(buf, size);
-	return *size > threshold ? 1 :
-		ret == -2 ? -2 :
-		*size > 0 ? 0 : -1;
-}
-
-IBuffer *_i_buffer_create(_IBuffer *_buf, Pool pool, int fd,
-			  uoff_t start_offset, uoff_t v_size)
-{
-	_buf->fd = fd;
-	_buf->ibuffer.start_offset = start_offset;
-	_buf->ibuffer.v_size = v_size;
-	_buf->ibuffer.v_limit = v_size;
-	_buf->ibuffer.real_buffer = _buf;
-
-	_io_buffer_init(pool, &_buf->iobuf);
-	return &_buf->ibuffer;
-}
--- a/src/lib/ibuffer.h	Fri Dec 06 00:37:33 2002 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,74 +0,0 @@
-#ifndef __IBUFFER_H
-#define __IBUFFER_H
-
-struct _IBuffer {
-	uoff_t start_offset;
-	uoff_t v_offset, v_size, v_limit; /* relative to start_offset */
-
-	int buf_errno;
-	unsigned int closed:1;
-
-	void *real_buffer;
-};
-
-IBuffer *i_buffer_create_file(int fd, Pool pool, size_t max_buffer_size,
-			      int autoclose_fd);
-IBuffer *i_buffer_create_mmap(int fd, Pool pool, size_t block_size,
-			      uoff_t start_offset, uoff_t v_size,
-			      int autoclose_fd);
-IBuffer *i_buffer_create_from_data(Pool pool, const unsigned char *data,
-				   size_t size);
-
-/* Reference counting. References start from 1, so calling i_buffer_unref()
-   destroys the buffer if i_buffer_ref() is never used. */
-void i_buffer_ref(IBuffer *buf);
-void i_buffer_unref(IBuffer *buf);
-
-/* Return file descriptor for buffer, or -1 if none is available. */
-int i_buffer_get_fd(IBuffer *buf);
-
-/* Mark the buffer closed. Any reads after this will return -1. The data
-   already in buffer can still be used. */
-void i_buffer_close(IBuffer *buf);
-
-/* Change the maximum size for buffer to grow. */
-void i_buffer_set_max_size(IBuffer *buf, size_t max_size);
-/* Change the start_offset and drop all data in buffers. Doesn't do anything
-   if offset is the same as existing start_offset. */
-void i_buffer_set_start_offset(IBuffer *buf, uoff_t offset);
-/* Input buffer won't be read past specified offset. Giving 0 as offset
-   removes the limit. The offset is  */
-void i_buffer_set_read_limit(IBuffer *buf, uoff_t v_offset);
-/* Makes reads blocking until at least one byte is read. timeout_func is
-   called if nothing is read in specified time. Setting timeout_msecs to 0
-   makes it non-blocking. This call changes non-blocking state of file
-   descriptor. */
-void i_buffer_set_blocking(IBuffer *buf, int timeout_msecs,
-			   void (*timeout_func)(void *), void *context);
-
-/* Returns number of bytes read if read was ok, -1 if EOF or error, -2 if the
-   buffer is full. */
-ssize_t i_buffer_read(IBuffer *buf);
-/* Skip forward a number of bytes. Never fails, the next read tells if it
-   was successful. */
-void i_buffer_skip(IBuffer *buf, uoff_t count);
-/* Seek to specified position from beginning of file. Never fails, the next
-   read tells if it was successful. This works only for files. */
-void i_buffer_seek(IBuffer *buf, uoff_t v_offset);
-/* Returns the next line from input buffer, or NULL if more data is needed
-   to make a full line. NOTE: modifies the data in the buffer for the \0, so
-   it works only with ibuffers that allow it (currently only file). */
-char *i_buffer_next_line(IBuffer *buf);
-/* Returns pointer to beginning of data in buffer, or NULL if there's
-   no data. */
-const unsigned char *i_buffer_get_data(IBuffer *buf, size_t *size);
-/* Like i_buffer_get_data(), but returns non-const data. If modifying isn't
-   allowed to buffer, returns NULL. */
-unsigned char *i_buffer_get_modifyable_data(IBuffer *buf, size_t *size);
-/* Like i_buffer_get_data(), but read it when needed. Returns 1 if more
-   than threshold bytes were stored into buffer, 0 if less, -1 if error or
-   EOF with no bytes in buffer or -2 if buffer is full. */
-int i_buffer_read_data(IBuffer *buf, const unsigned char **data,
-		       size_t *size, size_t threshold);
-
-#endif
--- a/src/lib/iobuffer-internal.h	Fri Dec 06 00:37:33 2002 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,33 +0,0 @@
-#ifndef __IOBUFFER_INTERNAL_H
-#define __IOBUFFER_INTERNAL_H
-
-/* This file is private to IBuffer and OBuffer implementation */
-
-typedef struct _IOBuffer _IOBuffer;
-
-struct _IOBuffer {
-	Pool pool;
-	int refcount;
-
-	void (*close)(_IOBuffer *buf);
-	void (*destroy)(_IOBuffer *buf);
-	void (*set_max_size)(_IOBuffer *buf, size_t max_size);
-	void (*set_blocking)(_IOBuffer *buf, int timeout_msecs,
-			     void (*timeout_func)(void *), void *context);
-};
-
-void _io_buffer_init(Pool pool, _IOBuffer *buf);
-void _io_buffer_ref(_IOBuffer *buf);
-void _io_buffer_unref(_IOBuffer *buf);
-void _io_buffer_close(_IOBuffer *buf);
-void _io_buffer_set_max_size(_IOBuffer *buf, size_t max_size);
-void _io_buffer_set_blocking(_IOBuffer *buf, int timeout_msecs,
-			     void (*timeout_func)(void *), void *context);
-
-#define GET_TIMEOUT_TIME(fbuf) \
-        ((fbuf)->timeout_msecs == 0 ? 0 : \
-	 time(NULL) + ((fbuf)->timeout_msecs / 1000))
-#define BUFFER_IS_BLOCKING(fbuf) \
-	((fbuf)->timeout_msecs != 0)
-
-#endif
--- a/src/lib/iobuffer.c	Fri Dec 06 00:37:33 2002 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,70 +0,0 @@
-/*
-   iobuffer.c : Input/output buffer common handling
-
-    Copyright (c) 2002 Timo Sirainen
-
-    Permission is hereby granted, free of charge, to any person obtaining
-    a copy of this software and associated documentation files (the
-    "Software"), to deal in the Software without restriction, including
-    without limitation the rights to use, copy, modify, merge, publish,
-    distribute, sublicense, and/or sell copies of the Software, and to
-    permit persons to whom the Software is furnished to do so, subject to
-    the following conditions:
-
-    The above copyright notice and this permission notice shall be
-    included in all copies or substantial portions of the Software.
-
-    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-    TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-    SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-*/
-
-#include "lib.h"
-#include "iobuffer-internal.h"
-
-void _io_buffer_init(Pool pool, _IOBuffer *buf)
-{
-	buf->pool = pool;
-	buf->refcount = 1;
-}
-
-void _io_buffer_ref(_IOBuffer *buf)
-{
-	buf->refcount++;
-}
-
-void _io_buffer_unref(_IOBuffer *buf)
-{
-	Pool pool;
-
-	i_assert(buf->refcount > 0);
-	if (--buf->refcount != 0)
-		return;
-
-	buf->close(buf);
-	buf->destroy(buf);
-
-	pool = buf->pool;
-        p_free(pool, buf);
-	pool_unref(pool);
-}
-
-void _io_buffer_close(_IOBuffer *buf)
-{
-	buf->close(buf);
-}
-
-void _io_buffer_set_max_size(_IOBuffer *buf, size_t max_size)
-{
-	buf->set_max_size(buf, max_size);
-}
-
-void _io_buffer_set_blocking(_IOBuffer *buf, int timeout_msecs,
-			     void (*timeout_func)(void *), void *context)
-{
-	buf->set_blocking(buf, timeout_msecs, timeout_func, context);
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib/iostream-internal.h	Fri Dec 06 03:09:22 2002 +0200
@@ -0,0 +1,33 @@
+#ifndef __IOSTREAM_INTERNAL_H
+#define __IOSTREAM_INTERNAL_H
+
+/* This file is private to IStream and OStream implementation */
+
+typedef struct _IOStream _IOStream;
+
+struct _IOStream {
+	Pool pool;
+	int refcount;
+
+	void (*close)(_IOStream *stream);
+	void (*destroy)(_IOStream *stream);
+	void (*set_max_buffer_size)(_IOStream *stream, size_t max_size);
+	void (*set_blocking)(_IOStream *stream, int timeout_msecs,
+			     void (*timeout_func)(void *), void *context);
+};
+
+void _io_stream_init(Pool pool, _IOStream *stream);
+void _io_stream_ref(_IOStream *stream);
+void _io_stream_unref(_IOStream *stream);
+void _io_stream_close(_IOStream *stream);
+void _io_stream_set_max_buffer_size(_IOStream *stream, size_t max_size);
+void _io_stream_set_blocking(_IOStream *stream, int timeout_msecs,
+			     void (*timeout_func)(void *), void *context);
+
+#define GET_TIMEOUT_TIME(fstream) \
+        ((fstream)->timeout_msecs == 0 ? 0 : \
+	 time(NULL) + ((fstream)->timeout_msecs / 1000))
+#define STREAM_IS_BLOCKING(fstream) \
+	((fstream)->timeout_msecs != 0)
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib/iostream.c	Fri Dec 06 03:09:22 2002 +0200
@@ -0,0 +1,70 @@
+/*
+   iostream.c : Input/output stream common handling
+
+    Copyright (c) 2002 Timo Sirainen
+
+    Permission is hereby granted, free of charge, to any person obtaining
+    a copy of this software and associated documentation files (the
+    "Software"), to deal in the Software without restriction, including
+    without limitation the rights to use, copy, modify, merge, publish,
+    distribute, sublicense, and/or sell copies of the Software, and to
+    permit persons to whom the Software is furnished to do so, subject to
+    the following conditions:
+
+    The above copyright notice and this permission notice shall be
+    included in all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+    TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+    SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include "lib.h"
+#include "iostream-internal.h"
+
+void _io_stream_init(Pool pool, _IOStream *stream)
+{
+	stream->pool = pool;
+	stream->refcount = 1;
+}
+
+void _io_stream_ref(_IOStream *stream)
+{
+	stream->refcount++;
+}
+
+void _io_stream_unref(_IOStream *stream)
+{
+	Pool pool;
+
+	i_assert(stream->refcount > 0);
+	if (--stream->refcount != 0)
+		return;
+
+	stream->close(stream);
+	stream->destroy(stream);
+
+	pool = stream->pool;
+        p_free(pool, stream);
+	pool_unref(pool);
+}
+
+void _io_stream_close(_IOStream *stream)
+{
+	stream->close(stream);
+}
+
+void _io_stream_set_max_buffer_size(_IOStream *stream, size_t max_size)
+{
+	stream->set_max_buffer_size(stream, max_size);
+}
+
+void _io_stream_set_blocking(_IOStream *stream, int timeout_msecs,
+			     void (*timeout_func)(void *), void *context)
+{
+	stream->set_blocking(stream, timeout_msecs, timeout_func, context);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib/istream-data.c	Fri Dec 06 03:09:22 2002 +0200
@@ -0,0 +1,85 @@
+/*
+   istream-data.c : Input stream interface for reading from data buffer
+
+    Copyright (c) 2002 Timo Sirainen
+
+    Permission is hereby granted, free of charge, to any person obtaining
+    a copy of this software and associated documentation files (the
+    "Software"), to deal in the Software without restriction, including
+    without limitation the rights to use, copy, modify, merge, publish,
+    distribute, sublicense, and/or sell copies of the Software, and to
+    permit persons to whom the Software is furnished to do so, subject to
+    the following conditions:
+
+    The above copyright notice and this permission notice shall be
+    included in all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+    TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+    SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include "lib.h"
+#include "istream-internal.h"
+
+static void _close(_IOStream *stream __attr_unused__)
+{
+}
+
+static void _destroy(_IOStream *stream __attr_unused__)
+{
+}
+
+static void _set_max_buffer_size(_IOStream *stream __attr_unused__,
+				 size_t max_size __attr_unused__)
+{
+}
+
+static void _set_blocking(_IOStream *stream __attr_unused__,
+			  int timeout_msecs __attr_unused__,
+			  void (*timeout_func)(void *) __attr_unused__,
+			  void *context __attr_unused__)
+{
+}
+
+static ssize_t _read(_IStream *stream)
+{
+	return stream->pos - stream->skip;
+}
+
+static void _seek(_IStream *stream, uoff_t v_offset)
+{
+	stream->skip = v_offset;
+	stream->istream.v_offset = v_offset;
+}
+
+static void _skip(_IStream *stream, uoff_t count)
+{
+	stream->skip += count;
+	stream->istream.v_offset += count;
+}
+
+IStream *i_stream_create_from_data(Pool pool, const unsigned char *data,
+				   size_t size)
+{
+	_IStream *stream;
+
+	stream = p_new(pool, _IStream, 1);
+	stream->buffer = data;
+	stream->pos = size;
+
+	stream->iostream.close = _close;
+	stream->iostream.destroy = _destroy;
+	stream->iostream.set_max_buffer_size = _set_max_buffer_size;
+	stream->iostream.set_blocking = _set_blocking;
+
+	stream->read = _read;
+	stream->skip_count = _skip;
+	stream->seek = _seek;
+
+	return _i_stream_create(stream, pool, -1, 0, size);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib/istream-file.c	Fri Dec 06 03:09:22 2002 +0200
@@ -0,0 +1,294 @@
+/*
+   istream-file.c : Input stream handling for files
+
+    Copyright (c) 2002 Timo Sirainen
+
+    Permission is hereby granted, free of charge, to any person obtaining
+    a copy of this software and associated documentation files (the
+    "Software"), to deal in the Software without restriction, including
+    without limitation the rights to use, copy, modify, merge, publish,
+    distribute, sublicense, and/or sell copies of the Software, and to
+    permit persons to whom the Software is furnished to do so, subject to
+    the following conditions:
+
+    The above copyright notice and this permission notice shall be
+    included in all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+    TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+    SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include "lib.h"
+#include "alarm-hup.h"
+#include "istream-internal.h"
+#include "network.h"
+
+#include <time.h>
+#include <unistd.h>
+#include <sys/stat.h>
+
+#define I_STREAM_MIN_SIZE 4096
+
+#define STREAM_IS_BLOCKING(fstream) \
+	((fstream)->timeout_msecs != 0)
+
+typedef struct {
+	_IStream istream;
+
+	size_t max_buffer_size;
+	uoff_t skip_left;
+
+	int timeout_msecs;
+	void (*timeout_func)(void *);
+	void *timeout_context;
+
+	unsigned int file:1;
+	unsigned int autoclose_fd:1;
+} FileIStream;
+
+static void _close(_IOStream *stream)
+{
+	FileIStream *fstream = (FileIStream *) stream;
+	_IStream *_stream = (_IStream *) stream;
+
+	if (fstream->autoclose_fd && _stream->fd != -1) {
+		if (close(_stream->fd) < 0)
+			i_error("FileIStream.close() failed: %m");
+		_stream->fd = -1;
+	}
+}
+
+static void _destroy(_IOStream *stream)
+{
+	_IStream *_stream = (_IStream *) stream;
+
+	p_free(_stream->iostream.pool, _stream->w_buffer);
+}
+
+static void _set_max_buffer_size(_IOStream *stream, size_t max_size)
+{
+	FileIStream *fstream = (FileIStream *) stream;
+
+	fstream->max_buffer_size = max_size;
+}
+
+static void _set_blocking(_IOStream *stream, int timeout_msecs,
+			  void (*timeout_func)(void *), void *context)
+{
+	FileIStream *fstream = (FileIStream *) stream;
+
+	fstream->timeout_msecs = timeout_msecs;
+	fstream->timeout_func = timeout_func;
+	fstream->timeout_context = context;
+
+	net_set_nonblock(fstream->istream.fd, timeout_msecs == 0);
+
+	if (timeout_msecs != 0)
+		alarm_hup_init();
+}
+
+static void i_stream_grow_buffer(_IStream *stream, size_t bytes)
+{
+	FileIStream *fstream = (FileIStream *) stream;
+
+	stream->buffer_size = stream->pos + bytes;
+	stream->buffer_size =
+		stream->buffer_size <= I_STREAM_MIN_SIZE ? I_STREAM_MIN_SIZE :
+		nearest_power(stream->buffer_size);
+
+	if (fstream->max_buffer_size > 0 &&
+	    stream->buffer_size > fstream->max_buffer_size)
+		stream->buffer_size = fstream->max_buffer_size;
+
+	stream->buffer = stream->w_buffer =
+		p_realloc(stream->iostream.pool, stream->w_buffer,
+			  stream->buffer_size);
+}
+
+static void i_stream_compress(_IStream *stream)
+{
+	memmove(stream->w_buffer, stream->w_buffer + stream->skip,
+		stream->pos - stream->skip);
+	stream->pos -= stream->skip;
+
+	if (stream->skip > stream->cr_lookup_pos)
+		stream->cr_lookup_pos = 0;
+	else
+		stream->cr_lookup_pos -= stream->skip;
+
+	stream->skip = 0;
+}
+
+static ssize_t _read(_IStream *stream)
+{
+	FileIStream *fstream = (FileIStream *) stream;
+	time_t timeout_time;
+	uoff_t read_limit;
+	size_t size;
+	ssize_t ret;
+
+	if (stream->istream.closed)
+		return -1;
+
+	if (fstream->skip_left > 0) {
+		i_assert(stream->skip == stream->pos);
+
+		if (fstream->file) {
+			/* we're a file, so we can lseek() */
+			i_stream_seek(&stream->istream,
+				      stream->istream.v_offset);
+			if (stream->istream.closed)
+				return -1;
+		}
+	}
+
+	stream->istream.stream_errno = 0;
+
+	if (stream->pos == stream->buffer_size) {
+		if (stream->skip > 0) {
+			/* remove the unused bytes from beginning of buffer */
+                        i_stream_compress(stream);
+		} else if (fstream->max_buffer_size == 0 ||
+			   stream->buffer_size < fstream->max_buffer_size) {
+			/* buffer is full - grow it */
+			i_stream_grow_buffer(stream, I_STREAM_MIN_SIZE);
+		}
+
+		if (stream->pos == stream->buffer_size)
+			return -2; /* buffer full */
+	}
+
+	size = stream->buffer_size - stream->pos;
+	if (stream->istream.v_limit > 0) {
+		i_assert(stream->istream.v_limit >= stream->istream.v_offset);
+
+		read_limit = stream->istream.v_limit -
+			stream->istream.v_offset + fstream->skip_left;
+		if (read_limit <= stream->pos - stream->skip) {
+			/* virtual limit reached == EOF */
+			return -1;
+		}
+
+		read_limit -= stream->pos - stream->skip;
+		if (size > read_limit)
+			size = read_limit;
+	}
+
+	timeout_time = GET_TIMEOUT_TIME(fstream);
+
+	ret = -1;
+	do {
+		if (ret == 0 && timeout_time > 0 && time(NULL) > timeout_time) {
+			/* timeouted */
+			if (fstream->timeout_func != NULL)
+				fstream->timeout_func(fstream->timeout_context);
+			stream->istream.stream_errno = EAGAIN;
+			return -1;
+		}
+
+		ret = read(stream->fd, stream->w_buffer + stream->pos, size);
+		if (ret == 0) {
+			/* EOF */
+			stream->istream.stream_errno = 0;
+			return -1;
+		}
+
+		if (ret < 0) {
+			if (errno == EINTR || errno == EAGAIN)
+				ret = 0;
+			else {
+				stream->istream.stream_errno = errno;
+				return -1;
+			}
+		}
+
+		if (ret > 0 && fstream->skip_left > 0) {
+			if (fstream->skip_left >= (size_t)ret) {
+				fstream->skip_left -= ret;
+				ret = 0;
+			} else {
+				ret -= fstream->skip_left;
+				stream->pos += fstream->skip_left;
+				stream->skip += fstream->skip_left;
+				fstream->skip_left = 0;
+			}
+		}
+	} while (ret == 0 && STREAM_IS_BLOCKING(fstream));
+
+	stream->pos += ret;
+	return ret;
+}
+
+static void _skip(_IStream *stream, uoff_t count)
+{
+	FileIStream *fstream = (FileIStream *) stream;
+
+	fstream->skip_left += count - (stream->pos - stream->skip);
+	stream->skip = stream->pos = 0;
+	stream->istream.v_offset += count;
+}
+
+static void _seek(_IStream *stream, uoff_t v_offset)
+{
+	FileIStream *fstream = (FileIStream *) stream;
+	uoff_t real_offset;
+	off_t ret;
+
+	real_offset = stream->istream.start_offset + v_offset;
+	if (real_offset > OFF_T_MAX) {
+		stream->istream.stream_errno = EOVERFLOW;
+		ret = -1;
+	} else {
+		ret = lseek(stream->fd, (off_t)real_offset, SEEK_SET);
+		if (ret < 0)
+			stream->istream.stream_errno = errno;
+		else if (ret != (off_t)real_offset) {
+			stream->istream.stream_errno = EINVAL;
+			ret = -1;
+		} else {
+			stream->skip = stream->pos = 0;
+			fstream->skip_left = 0;
+		}
+	}
+
+	if (ret < 0)
+                i_stream_close(&stream->istream);
+	else {
+		stream->istream.stream_errno = 0;
+		stream->istream.v_offset = v_offset;
+	}
+}
+
+IStream *i_stream_create_file(int fd, Pool pool, size_t max_buffer_size,
+			      int autoclose_fd)
+{
+	FileIStream *fstream;
+	struct stat st;
+
+	fstream = p_new(pool, FileIStream, 1);
+	fstream->max_buffer_size = max_buffer_size;
+	fstream->autoclose_fd = autoclose_fd;
+
+	fstream->istream.iostream.close = _close;
+	fstream->istream.iostream.destroy = _destroy;
+	fstream->istream.iostream.set_max_buffer_size = _set_max_buffer_size;
+	fstream->istream.iostream.set_blocking = _set_blocking;
+
+	fstream->istream.read = _read;
+	fstream->istream.skip_count = _skip;
+	fstream->istream.seek = _seek;
+
+	/* get size of fd if it's a file */
+	if (fstat(fd, &st) < 0)
+		st.st_size = 0;
+	else if (S_ISREG(st.st_mode))
+		fstream->file = TRUE;
+
+	return _i_stream_create(&fstream->istream, pool, fd, 0,
+				(uoff_t)st.st_size);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib/istream-internal.h	Fri Dec 06 03:09:22 2002 +0200
@@ -0,0 +1,32 @@
+#ifndef __ISTREAM_INTERNAL_H
+#define __ISTREAM_INTERNAL_H
+
+#include "istream.h"
+#include "iostream-internal.h"
+
+typedef struct __IStream _IStream;
+
+struct __IStream {
+/* inheritance: */
+	_IOStream iostream;
+
+/* methods: */
+	ssize_t (*read)(_IStream *stream);
+	void (*skip_count)(_IStream *stream, uoff_t count);
+	void (*seek)(_IStream *stream, uoff_t v_offset);
+
+/* data: */
+	IStream istream;
+
+	int fd;
+	const unsigned char *buffer;
+	unsigned char *w_buffer; /* may be NULL */
+	size_t buffer_size;
+
+	size_t skip, pos, cr_lookup_pos;
+};
+
+IStream *_i_stream_create(_IStream *_buf, Pool pool, int fd,
+			  uoff_t start_offset, uoff_t v_size);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib/istream-mmap.c	Fri Dec 06 03:09:22 2002 +0200
@@ -0,0 +1,241 @@
+/*
+   istream-mmap.c : Input stream handling for mmap()ed files
+
+    Copyright (c) 2002 Timo Sirainen
+
+    Permission is hereby granted, free of charge, to any person obtaining
+    a copy of this software and associated documentation files (the
+    "Software"), to deal in the Software without restriction, including
+    without limitation the rights to use, copy, modify, merge, publish,
+    distribute, sublicense, and/or sell copies of the Software, and to
+    permit persons to whom the Software is furnished to do so, subject to
+    the following conditions:
+
+    The above copyright notice and this permission notice shall be
+    included in all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+    TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+    SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include "lib.h"
+#include "mmap-util.h"
+#include "istream-internal.h"
+
+#include <unistd.h>
+#include <sys/stat.h>
+
+typedef struct {
+	_IStream istream;
+
+	int fd;
+	void *mmap_base;
+	off_t mmap_offset;
+	size_t mmap_block_size;
+
+	unsigned int autoclose_fd:1;
+} MmapIStream;
+
+static size_t mmap_pagesize = 0;
+static size_t mmap_pagemask = 0;
+
+static void _close(_IOStream *stream)
+{
+	MmapIStream *mstream = (MmapIStream *) stream;
+
+	if (mstream->autoclose_fd && mstream->fd != -1) {
+		if (close(mstream->fd) < 0)
+			i_error("MmapIStream.close() failed: %m");
+		mstream->fd = -1;
+	}
+}
+
+static void i_stream_munmap(MmapIStream *mstream)
+{
+	_IStream *_stream = &mstream->istream;
+
+	if (_stream->buffer != NULL) {
+		if (munmap(mstream->mmap_base, _stream->buffer_size) < 0)
+			i_error("MmapIStream.munmap() failed: %m");
+		mstream->mmap_base = NULL;
+		_stream->buffer = NULL;
+		_stream->buffer_size = 0;
+		mstream->mmap_offset = 0;
+	}
+}
+
+static void _destroy(_IOStream *stream)
+{
+	MmapIStream *mstream = (MmapIStream *) stream;
+
+	i_stream_munmap(mstream);
+}
+
+static void _set_max_buffer_size(_IOStream *stream, size_t max_size)
+{
+	MmapIStream *mstream = (MmapIStream *) stream;
+
+	mstream->mmap_block_size = max_size;
+}
+
+static void _set_blocking(_IOStream *stream __attr_unused__,
+			  int timeout_msecs __attr_unused__,
+			  void (*timeout_func)(void *) __attr_unused__,
+			  void *context __attr_unused__)
+{
+	/* we never block */
+}
+
+static ssize_t io_stream_set_mmaped_pos(_IStream *stream)
+{
+	MmapIStream *mstream = (MmapIStream *) stream;
+
+	i_assert((uoff_t)mstream->mmap_offset <=
+		 stream->istream.start_offset + stream->istream.v_limit);
+
+	stream->pos = stream->istream.start_offset + stream->istream.v_limit -
+		mstream->mmap_offset;
+	if (stream->pos > stream->buffer_size)
+		stream->pos = stream->buffer_size;
+
+	return stream->pos - stream->skip;
+}
+
+static ssize_t _read(_IStream *stream)
+{
+	MmapIStream *mstream = (MmapIStream *) stream;
+	size_t aligned_skip, limit_size;
+
+	if (stream->istream.start_offset + stream->istream.v_limit <=
+	    (uoff_t)mstream->mmap_offset + stream->pos) {
+		/* end of file */
+		stream->istream.stream_errno = 0;
+		return -1;
+	}
+
+	if (stream->pos < stream->buffer_size) {
+		/* more bytes available without needing to mmap() */
+		return io_stream_set_mmaped_pos(stream);
+	}
+
+	aligned_skip = stream->skip & ~mmap_pagemask;
+	if (aligned_skip == 0 && mstream->mmap_base != NULL) {
+		/* didn't skip enough bytes */
+		return -2;
+	}
+
+	stream->skip -= aligned_skip;
+	mstream->mmap_offset += aligned_skip;
+
+	if (mstream->mmap_base != NULL) {
+		if (munmap(mstream->mmap_base, stream->buffer_size) < 0)
+			i_error("io_stream_read_mmaped(): munmap() failed: %m");
+	}
+
+	stream->buffer_size = stream->istream.start_offset +
+		stream->istream.v_size - mstream->mmap_offset;
+	if (stream->buffer_size > mstream->mmap_block_size)
+		stream->buffer_size = mstream->mmap_block_size;
+
+	i_assert((uoff_t)mstream->mmap_offset + stream->buffer_size <=
+		 stream->istream.start_offset + stream->istream.v_size);
+
+	mstream->mmap_base = mmap(NULL, stream->buffer_size,
+				  PROT_READ, MAP_PRIVATE,
+				  mstream->fd, mstream->mmap_offset);
+	stream->buffer = mstream->mmap_base;
+	if (mstream->mmap_base == MAP_FAILED) {
+		stream->istream.stream_errno = errno;
+		mstream->mmap_base = NULL;
+		stream->buffer = NULL;
+		stream->buffer_size = 0;
+		stream->skip = stream->pos = 0;
+		i_error("MmapIStream.mmap() failed: %m");
+		return -1;
+	}
+
+	/* madvise() only if non-limited mmap()ed buffer area larger than
+	   page size */
+	limit_size = stream->istream.start_offset + stream->istream.v_limit -
+		mstream->mmap_offset;
+	if (limit_size > mmap_pagesize) {
+		if (limit_size > stream->buffer_size)
+			limit_size = stream->buffer_size;
+
+		if (madvise(mstream->mmap_base, limit_size, MADV_SEQUENTIAL) < 0)
+			i_error("MmapIStream.madvise(): %m");
+	}
+
+	return io_stream_set_mmaped_pos(stream);
+}
+
+static void _seek(_IStream *stream, uoff_t v_offset)
+{
+	MmapIStream *mstream = (MmapIStream *) stream;
+	uoff_t abs_offset;
+
+	abs_offset = stream->istream.start_offset + v_offset;
+	if (stream->buffer_size != 0 &&
+	    (uoff_t)mstream->mmap_offset <= abs_offset &&
+	    (uoff_t)mstream->mmap_offset + stream->buffer_size > abs_offset) {
+		/* already mmaped */
+		stream->skip = stream->pos = abs_offset - mstream->mmap_offset;
+	} else {
+		/* force reading next time */
+		i_stream_munmap(mstream);
+		stream->skip = stream->pos = abs_offset;
+	}
+
+	stream->istream.v_offset = v_offset;
+}
+
+static void _skip(_IStream *stream, uoff_t count)
+{
+	_seek(stream, stream->istream.v_offset + count);
+}
+
+IStream *i_stream_create_mmap(int fd, Pool pool, size_t block_size,
+			      uoff_t start_offset, uoff_t v_size,
+			      int autoclose_fd)
+{
+	MmapIStream *mstream;
+	struct stat st;
+
+	if (mmap_pagesize == 0) {
+		mmap_pagesize = getpagesize();
+		mmap_pagemask = mmap_pagesize-1;
+	}
+
+	if (v_size == 0) {
+		if (fstat(fd, &st) < 0) {
+			i_error("i_stream_create_mmap(): fstat() failed: %m");
+			v_size = 0;
+		} else {
+			v_size = st.st_size;
+			if (start_offset > v_size)
+				start_offset = v_size;
+			v_size -= start_offset;
+		}
+	}
+
+	mstream = p_new(pool, MmapIStream, 1);
+	mstream->fd = fd;
+	mstream->mmap_block_size = block_size;
+	mstream->autoclose_fd = autoclose_fd;
+
+	mstream->istream.iostream.close = _close;
+	mstream->istream.iostream.destroy = _destroy;
+	mstream->istream.iostream.set_max_buffer_size = _set_max_buffer_size;
+	mstream->istream.iostream.set_blocking = _set_blocking;
+
+	mstream->istream.read = _read;
+	mstream->istream.skip_count = _skip;
+	mstream->istream.seek = _seek;
+
+	return _i_stream_create(&mstream->istream, pool, fd, start_offset, v_size);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib/istream.c	Fri Dec 06 03:09:22 2002 +0200
@@ -0,0 +1,247 @@
+/*
+   istream.c : Input stream handling
+
+    Copyright (c) 2002 Timo Sirainen
+
+    Permission is hereby granted, free of charge, to any person obtaining
+    a copy of this software and associated documentation files (the
+    "Software"), to deal in the Software without restriction, including
+    without limitation the rights to use, copy, modify, merge, publish,
+    distribute, sublicense, and/or sell copies of the Software, and to
+    permit persons to whom the Software is furnished to do so, subject to
+    the following conditions:
+
+    The above copyright notice and this permission notice shall be
+    included in all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+    TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+    SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include "lib.h"
+#include "istream-internal.h"
+
+void i_stream_ref(IStream *stream)
+{
+	_io_stream_ref(stream->real_stream);
+}
+
+void i_stream_unref(IStream *stream)
+{
+	_io_stream_unref(stream->real_stream);
+}
+
+int i_stream_get_fd(IStream *stream)
+{
+	_IStream *_stream = stream->real_stream;
+
+	return _stream->fd;
+}
+
+void i_stream_close(IStream *stream)
+{
+	_io_stream_close(stream->real_stream);
+	stream->closed = TRUE;
+}
+
+void i_stream_set_max_buffer_size(IStream *stream, size_t max_size)
+{
+	_io_stream_set_max_buffer_size(stream->real_stream, max_size);
+}
+
+void i_stream_set_blocking(IStream *stream, int timeout_msecs,
+			   void (*timeout_func)(void *), void *context)
+{
+	_io_stream_set_blocking(stream->real_stream, timeout_msecs,
+				timeout_func, context);
+}
+
+void i_stream_set_start_offset(IStream *stream, uoff_t offset)
+{
+	_IStream *_stream = stream->real_stream;
+	off_t diff;
+
+	i_assert(stream->v_size == 0 ||
+		 offset <= stream->start_offset + stream->v_size);
+
+	if (offset == stream->start_offset)
+		return;
+
+	diff = (off_t)stream->start_offset - (off_t)offset;
+	stream->start_offset = offset;
+	stream->v_offset += diff;
+	if (stream->v_size != 0) {
+		stream->v_size += diff;
+		stream->v_limit += diff;
+	}
+
+	/* reset buffer data */
+	_stream->skip = _stream->pos = _stream->cr_lookup_pos = 0;
+}
+
+void i_stream_set_read_limit(IStream *stream, uoff_t v_offset)
+{
+	_IStream *_stream = stream->real_stream;
+	uoff_t max_pos;
+
+	i_assert(stream->v_size == 0 || v_offset <= stream->v_size);
+
+	if (v_offset == 0)
+		stream->v_limit = stream->v_size;
+	else {
+		i_assert(v_offset >= stream->v_offset);
+
+		stream->v_limit = v_offset;
+		max_pos = v_offset - stream->v_offset + _stream->skip;
+		if (_stream->pos > max_pos)
+			_stream->pos = max_pos;
+	}
+}
+
+ssize_t i_stream_read(IStream *stream)
+{
+	_IStream *_stream = stream->real_stream;
+
+	if (stream->closed)
+		return -1;
+
+	return _stream->read(_stream);
+}
+
+void i_stream_skip(IStream *stream, uoff_t count)
+{
+	_IStream *_stream = stream->real_stream;
+	size_t data_size;
+
+	i_assert(stream->v_size == 0 ||
+		 stream->v_offset + count <= stream->v_size);
+
+	if (count <= _stream->pos - _stream->skip) {
+		stream->v_offset += count;
+		_stream->skip += count;
+		return;
+	}
+
+	if (stream->closed)
+		return;
+
+	data_size = _stream->pos - _stream->skip;
+	_stream->skip = _stream->pos;
+
+	count -= data_size;
+	stream->v_offset += data_size;
+
+	_stream->skip_count(_stream, count);
+}
+
+void i_stream_seek(IStream *stream, uoff_t v_offset)
+{
+	_IStream *_stream = stream->real_stream;
+
+	i_assert(v_offset <= stream->v_size);
+
+	if (stream->closed)
+		return;
+
+	_stream->seek(_stream, v_offset);
+}
+
+char *i_stream_next_line(IStream *stream)
+{
+	_IStream *_stream = stream->real_stream;
+	char *ret_buf;
+        size_t i;
+
+        i_assert(stream != NULL);
+
+	if (_stream->skip >= _stream->pos)
+		return NULL;
+
+	if (_stream->w_buffer == NULL) {
+		i_error("i_stream_next_line() called for unmodifyable stream");
+		return NULL;
+	}
+
+	ret_buf = NULL;
+	for (i = _stream->cr_lookup_pos; i < _stream->pos; i++) {
+		if (_stream->buffer[i] == 10) {
+			/* got it */
+			if (i > 0 && _stream->buffer[i-1] == '\r')
+				_stream->w_buffer[i-1] = '\0';
+			else
+				_stream->w_buffer[i] = '\0';
+			ret_buf = (char *) _stream->w_buffer + _stream->skip;
+
+			i++;
+			stream->v_offset += i - _stream->skip;
+			_stream->skip = i;
+                        break;
+		}
+	}
+
+	_stream->cr_lookup_pos = i;
+        return ret_buf;
+}
+
+const unsigned char *i_stream_get_data(IStream *stream, size_t *size)
+{
+	_IStream *_stream = stream->real_stream;
+
+	if (_stream->skip >= _stream->pos) {
+		*size = 0;
+		return NULL;
+	}
+
+        *size = _stream->pos - _stream->skip;
+        return _stream->buffer + _stream->skip;
+}
+
+unsigned char *i_stream_get_modifyable_data(IStream *stream, size_t *size)
+{
+	_IStream *_stream = stream->real_stream;
+
+	if (_stream->skip >= _stream->pos || _stream->w_buffer == NULL) {
+		*size = 0;
+		return NULL;
+	}
+
+        *size = _stream->pos - _stream->skip;
+        return _stream->w_buffer + _stream->skip;
+}
+
+int i_stream_read_data(IStream *stream, const unsigned char **data,
+		       size_t *size, size_t threshold)
+{
+	_IStream *_stream = stream->real_stream;
+	ssize_t ret = 0;
+
+	while (_stream->pos - _stream->skip <= threshold) {
+		/* we need more data */
+		ret = _stream->read(_stream);
+		if (ret < 0)
+			break;
+	}
+
+	*data = i_stream_get_data(stream, size);
+	return *size > threshold ? 1 :
+		ret == -2 ? -2 :
+		*size > 0 ? 0 : -1;
+}
+
+IStream *_i_stream_create(_IStream *_stream, Pool pool, int fd,
+			  uoff_t start_offset, uoff_t v_size)
+{
+	_stream->fd = fd;
+	_stream->istream.start_offset = start_offset;
+	_stream->istream.v_size = v_size;
+	_stream->istream.v_limit = v_size;
+	_stream->istream.real_stream = _stream;
+
+	_io_stream_init(pool, &_stream->iostream);
+	return &_stream->istream;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib/istream.h	Fri Dec 06 03:09:22 2002 +0200
@@ -0,0 +1,75 @@
+#ifndef __ISTREAM_H
+#define __ISTREAM_H
+
+struct _IStream {
+	uoff_t start_offset;
+	uoff_t v_offset, v_size, v_limit; /* relative to start_offset */
+
+	int stream_errno;
+	unsigned int closed:1;
+
+	void *real_stream;
+};
+
+IStream *i_stream_create_file(int fd, Pool pool, size_t max_buffer_size,
+			      int autoclose_fd);
+IStream *i_stream_create_mmap(int fd, Pool pool, size_t block_size,
+			      uoff_t start_offset, uoff_t v_size,
+			      int autoclose_fd);
+IStream *i_stream_create_from_data(Pool pool, const unsigned char *data,
+				   size_t size);
+
+/* Reference counting. References start from 1, so calling i_stream_unref()
+   destroys the stream if i_stream_ref() is never used. */
+void i_stream_ref(IStream *stream);
+void i_stream_unref(IStream *stream);
+
+/* Return file descriptor for stream, or -1 if none is available. */
+int i_stream_get_fd(IStream *stream);
+
+/* Mark the stream closed. Any reads after this will return -1. The data
+   already read can still be used. */
+void i_stream_close(IStream *stream);
+
+/* Change the maximum size for stream's input buffer to grow. Useful only
+   for buffered streams (currently only file). */
+void i_stream_set_max_buffer_size(IStream *stream, size_t max_size);
+/* Change the start_offset and drop all data in buffers. Doesn't do anything
+   if offset is the same as existing start_offset. */
+void i_stream_set_start_offset(IStream *stream, uoff_t offset);
+/* Stream won't be read past specified offset. Giving 0 as offset
+   removes the limit. */
+void i_stream_set_read_limit(IStream *stream, uoff_t v_offset);
+/* Makes reads blocking until at least one byte is read. timeout_func is
+   called if nothing is read in specified time. Setting timeout_msecs to 0
+   makes it non-blocking. This call changes non-blocking state of file
+   descriptor. */
+void i_stream_set_blocking(IStream *stream, int timeout_msecs,
+			   void (*timeout_func)(void *), void *context);
+
+/* Returns number of bytes read if read was ok, -1 if EOF or error, -2 if the
+   input buffer is full. */
+ssize_t i_stream_read(IStream *stream);
+/* Skip forward a number of bytes. Never fails, the next read tells if it
+   was successful. */
+void i_stream_skip(IStream *stream, uoff_t count);
+/* Seek to specified position from beginning of file. Never fails, the next
+   read tells if it was successful. This works only for files. */
+void i_stream_seek(IStream *stream, uoff_t v_offset);
+/* Reads the next line from stream and returns it, or NULL if more data is
+   needed to make a full line. NOTE: modifies the data in buffer for the \0,
+   so it works only with buffered streams (currently only file). */
+char *i_stream_next_line(IStream *stream);
+/* Returns pointer to beginning of read data, or NULL if there's no data
+   buffered. */
+const unsigned char *i_stream_get_data(IStream *stream, size_t *size);
+/* Like i_stream_get_data(), but returns non-const data. This only works with
+   buffered streams (currently only file), others return NULL. */
+unsigned char *i_stream_get_modifyable_data(IStream *stream, size_t *size);
+/* Like i_stream_get_data(), but read more when needed. Returns 1 if more
+   than threshold bytes are available, 0 if less, -1 if error or EOF with no
+   bytes available, or -2 if stream's input buffer is full. */
+int i_stream_read_data(IStream *stream, const unsigned char **data,
+		       size_t *size, size_t threshold);
+
+#endif
--- a/src/lib/lib.h	Fri Dec 06 00:37:33 2002 +0200
+++ b/src/lib/lib.h	Fri Dec 06 03:09:22 2002 +0200
@@ -22,8 +22,8 @@
 typedef struct _Timeout *Timeout;
 
 typedef struct _IPADDR IPADDR;
-typedef struct _IBuffer IBuffer;
-typedef struct _OBuffer OBuffer;
+typedef struct _IStream IStream;
+typedef struct _OStream OStream;
 typedef struct _TempString TempString;
 
 #include "compat.h"
--- a/src/lib/obuffer-file.c	Fri Dec 06 00:37:33 2002 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,678 +0,0 @@
-/*
-   obuffer-file.c : Output buffer handling for files
-
-    Copyright (c) 2002 Timo Sirainen
-
-    Permission is hereby granted, free of charge, to any person obtaining
-    a copy of this software and associated documentation files (the
-    "Software"), to deal in the Software without restriction, including
-    without limitation the rights to use, copy, modify, merge, publish,
-    distribute, sublicense, and/or sell copies of the Software, and to
-    permit persons to whom the Software is furnished to do so, subject to
-    the following conditions:
-
-    The above copyright notice and this permission notice shall be
-    included in all copies or substantial portions of the Software.
-
-    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-    TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-    SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-*/
-
-#include "lib.h"
-#include "alarm-hup.h"
-#include "ioloop.h"
-#include "network.h"
-#include "sendfile-util.h"
-#include "ibuffer.h"
-#include "obuffer-internal.h"
-
-#include <unistd.h>
-#ifdef HAVE_SYS_UIO_H
-#  include <sys/uio.h>
-#endif
-
-#define O_BUFFER_MIN_SIZE 4096
-
-#define IS_BUFFER_EMPTY(fbuf) \
-	(!(fbuf)->full && (fbuf)->head == (fbuf)->tail)
-
-#define MAX_SSIZE_T(size) \
-	((size) < SSIZE_T_MAX ? (size_t)(size) : SSIZE_T_MAX)
-
-typedef struct {
-	_OBuffer obuf;
-
-	int fd;
-	int priority;
-	IO io;
-
-	unsigned char *buffer; /* ring-buffer */
-	size_t buffer_size, max_buffer_size;
-	size_t head, tail; /* first unsent/unused byte */
-
-	int timeout_msecs;
-	void (*timeout_func)(void *);
-	void *timeout_context;
-
-	unsigned int full:1; /* if head == tail, is buffer empty or full? */
-	unsigned int corked:1;
-	unsigned int no_socket_cork:1;
-	unsigned int autoclose_fd:1;
-} FileOBuffer;
-
-static void buffer_closed(FileOBuffer *fbuf)
-{
-	if (fbuf->autoclose_fd && fbuf->fd != -1) {
-		if (close(fbuf->fd) < 0)
-			i_error("FileOBuffer.close() failed: %m");
-		fbuf->fd = -1;
-	}
-
-	if (fbuf->io != NULL) {
-		io_remove(fbuf->io);
-		fbuf->io = NULL;
-	}
-
-	fbuf->obuf.obuffer.closed = TRUE;
-}
-
-static void _close(_IOBuffer *buf)
-{
-	FileOBuffer *fbuf = (FileOBuffer *) buf;
-
-	/* flush output before really closing it */
-	o_buffer_flush(&fbuf->obuf.obuffer);
-
-	buffer_closed(fbuf);
-}
-
-static void _destroy(_IOBuffer *buf)
-{
-	FileOBuffer *fbuf = (FileOBuffer *) buf;
-
-	p_free(fbuf->obuf.iobuf.pool, fbuf->buffer);
-}
-
-static void _set_max_size(_IOBuffer *buf, size_t max_size)
-{
-	FileOBuffer *fbuf = (FileOBuffer *) buf;
-
-	fbuf->max_buffer_size = max_size;
-}
-
-static void _set_blocking(_IOBuffer *buf, int timeout_msecs,
-			  void (*timeout_func)(void *), void *context)
-{
-	FileOBuffer *fbuf = (FileOBuffer *) buf;
-
-	fbuf->timeout_msecs = timeout_msecs;
-	fbuf->timeout_func = timeout_func;
-	fbuf->timeout_context = context;
-
-	net_set_nonblock(fbuf->fd, timeout_msecs == 0);
-
-	if (timeout_msecs != 0)
-		alarm_hup_init();
-}
-
-static void _cork(_OBuffer *buf)
-{
-	FileOBuffer *fbuf = (FileOBuffer *) buf;
-
-	if (!fbuf->corked) {
-		if (!fbuf->no_socket_cork) {
-			if (net_set_cork(fbuf->fd, TRUE) < 0)
-				fbuf->no_socket_cork = TRUE;
-		}
-		fbuf->corked = TRUE;
-	}
-}
-
-static void update_iovec(struct iovec *iov, unsigned int iov_size, size_t size)
-{
-	while (size > 0) {
-		i_assert(iov_size > 0);
-
-		if ((size_t)iov->iov_len <= size) {
-			size -= iov->iov_len;
-			iov->iov_base = NULL;
-			iov->iov_len = 0;
-		} else {
-			iov->iov_base = (char *) iov->iov_base + size;
-			iov->iov_len -= size;
-			size = 0;
-		}
-		iov++; iov_size--;
-	}
-}
-
-static void update_buffer(FileOBuffer *fbuf, size_t size)
-{
-	size_t used;
-
-	if (IS_BUFFER_EMPTY(fbuf))
-		return;
-
-	if (fbuf->head < fbuf->tail) {
-		/* ...HXXXT... */
-		used = fbuf->tail - fbuf->head;
-		fbuf->head += I_MIN(used, size);
-	} else {
-		/* XXXT...HXXX */
-		used = fbuf->buffer_size - fbuf->head;
-		if (size > used) {
-			size -= used;
-			if (size < fbuf->tail)
-				fbuf->head = size;
-			else {
-				/* whole buffer is sent */
-				fbuf->head = fbuf->tail = 0;
-			}
-		} else {
-			fbuf->head += I_MIN(used, size);
-		}
-
-		fbuf->full = FALSE;
-	}
-
-	if (fbuf->head == fbuf->tail)
-		fbuf->head = fbuf->tail = 0;
-
-	if (fbuf->head == fbuf->buffer_size)
-		fbuf->head = 0;
-}
-
-/* NOTE: modifies iov */
-static ssize_t
-o_buffer_writev(FileOBuffer *fbuf, struct iovec *iov, int iov_size)
-{
-	ssize_t ret;
-
-	while (iov->iov_len == 0 && iov_size > 0) {
-		iov++;
-		iov_size--;
-	}
-
-	i_assert(iov_size > 0);
-
-	ret = writev(fbuf->fd, iov, iov_size);
-	if (ret < 0) {
-		if (errno == EAGAIN || errno == EINTR)
-			return 0;
-		buffer_closed(fbuf);
-		return -1;
-	}
-
-	update_iovec(iov, iov_size, ret);
-	update_buffer(fbuf, ret);
-	fbuf->obuf.obuffer.offset += ret;
-
-	return ret;
-}
-
-/* returns how much of vector was used */
-static int o_buffer_fill_iovec(FileOBuffer *fbuf, struct iovec iov[2])
-{
-	if (IS_BUFFER_EMPTY(fbuf))
-		return 0;
-
-	if (fbuf->head < fbuf->tail) {
-		iov[0].iov_base = fbuf->buffer + fbuf->head;
-		iov[0].iov_len = fbuf->tail - fbuf->head;
-		return 1;
-	} else {
-		iov[0].iov_base = fbuf->buffer + fbuf->head;
-		iov[0].iov_len = fbuf->buffer_size - fbuf->head;
-		if (fbuf->tail == 0)
-			return 1;
-		else {
-			iov[1].iov_base = fbuf->buffer;
-			iov[1].iov_len = fbuf->tail;
-			return 2;
-		}
-	}
-}
-
-static int o_buffer_send_blocking(FileOBuffer *fbuf, const void *data,
-				  size_t size)
-{
-	time_t timeout_time;
-	struct iovec iov[3];
-	int iov_len, first;
-
-	iov_len = o_buffer_fill_iovec(fbuf, iov);
-	if (size > 0) {
-		iov[iov_len].iov_base = (void *) data;
-		iov[iov_len].iov_len = size;
-		iov_len++;
-	}
-
-	first = TRUE;
-
-	timeout_time = GET_TIMEOUT_TIME(fbuf);
-	while (iov[iov_len-1].iov_len != 0) {
-		if (first)
-			first = FALSE;
-		else if (timeout_time > 0 && time(NULL) > timeout_time) {
-			/* timeouted */
-			if (fbuf->timeout_func != NULL)
-				fbuf->timeout_func(fbuf->timeout_context);
-			fbuf->obuf.obuffer.buf_errno = EAGAIN;
-			return -1;
-		}
-
-		if (o_buffer_writev(fbuf, iov, iov_len) < 0)
-			return -1;
-	}
-
-        return 1;
-}
-
-static int buffer_flush(FileOBuffer *fbuf)
-{
-	struct iovec iov[2];
-	int iov_len;
-
-	if (!IS_BUFFER_EMPTY(fbuf)) {
-		iov_len = o_buffer_fill_iovec(fbuf, iov);
-		if (o_buffer_writev(fbuf, iov, iov_len) < 0)
-			return -1;
-
-		if (!IS_BUFFER_EMPTY(fbuf)) {
-			if (o_buffer_send_blocking(fbuf, NULL, 0) < 0)
-				return -1;
-		}
-	}
-
-	return 1;
-}
-
-static int _flush(_OBuffer *buf)
-{
-	FileOBuffer *fbuf = (FileOBuffer *) buf;
-	int ret;
-
-	ret = buffer_flush(fbuf);
-
-	if (fbuf->corked) {
-		/* remove cork */
-		if (!fbuf->no_socket_cork) {
-			if (net_set_cork(fbuf->fd, FALSE) < 0)
-				i_error("net_set_cork() failed: %m");
-		}
-		fbuf->corked = FALSE;
-	}
-
-	return ret;
-}
-
-static size_t get_unused_space(FileOBuffer *fbuf)
-{
-	if (fbuf->head > fbuf->tail) {
-		/* XXXT...HXXX */
-		return fbuf->head - fbuf->tail;
-	} else if (fbuf->head < fbuf->tail) {
-		/* ...HXXXT... */
-		return (fbuf->buffer_size - fbuf->tail) + fbuf->head;
-	} else {
-		/* either fully unused or fully used */
-		return fbuf->full ? 0 : fbuf->buffer_size;
-	}
-}
-
-static int _have_space(_OBuffer *buf, size_t size)
-{
-	FileOBuffer *fbuf = (FileOBuffer *) buf;
-	size_t unused;
-
-	if (fbuf->max_buffer_size == 0)
-		return 1;
-
-	unused = get_unused_space(fbuf);
-	if (size <= unused)
-		return 1;
-
-	unused += (fbuf->max_buffer_size - fbuf->buffer_size);
-	return size <= unused ? 1 : 0;
-}
-
-static int _seek(_OBuffer *buf, uoff_t offset)
-{
-	FileOBuffer *fbuf = (FileOBuffer *) buf;
-	off_t ret;
-
-	if (offset > OFF_T_MAX) {
-		buf->obuffer.buf_errno = EINVAL;
-		return -1;
-	}
-
-	ret = lseek(fbuf->fd, (off_t)offset, SEEK_SET);
-	if (ret < 0) {
-		buf->obuffer.buf_errno = errno;
-		return -1;
-	}
-
-	if (ret != (off_t)offset) {
-		buf->obuffer.buf_errno = EINVAL;
-		return -1;
-	}
-
-	buf->obuffer.buf_errno = 0;
-	buf->obuffer.offset = offset;
-	return 1;
-}
-
-static void o_buffer_grow(FileOBuffer *fbuf, size_t bytes)
-{
-	size_t size, head_size;
-
-	size = nearest_power(fbuf->buffer_size + bytes);
-	if (fbuf->max_buffer_size != 0) {
-		if (size > fbuf->max_buffer_size) {
-			/* limit the size */
-			size = fbuf->max_buffer_size;
-		} else if (fbuf->corked) {
-			/* use the largest possible buffer with corking */
-			size = fbuf->max_buffer_size;
-		}
-	}
-
-	if (size == fbuf->buffer_size)
-		return;
-
-	fbuf->buffer = p_realloc(fbuf->obuf.iobuf.pool, fbuf->buffer, size);
-
-	if (fbuf->tail <= fbuf->head && !IS_BUFFER_EMPTY(fbuf)) {
-		head_size = I_MIN(fbuf->head, size - fbuf->buffer_size);
-		memcpy(fbuf->buffer + fbuf->buffer_size, fbuf->buffer,
-		       head_size);
-
-		if (head_size == fbuf->head)
-			fbuf->tail = fbuf->buffer_size + head_size;
-		else {
-			memmove(fbuf->buffer, fbuf->buffer + head_size,
-				fbuf->head - head_size);
-			fbuf->tail = fbuf->head - head_size;
-		}
-	}
-
-	fbuf->full = FALSE;
-	fbuf->buffer_size = size;
-}
-
-static void buffer_send_io(void *context, int fd __attr_unused__,
-			   IO io __attr_unused__)
-{
-	FileOBuffer *fbuf = context;
-	struct iovec iov[2];
-	int iov_len;
-
-	iov_len = o_buffer_fill_iovec(fbuf, iov);
-
-	if (iov_len == 0 || o_buffer_writev(fbuf, iov, iov_len) < 0 ||
-	    iov[iov_len-1].iov_len == 0) {
-		/* error / all sent */
-		io_remove(fbuf->io);
-                fbuf->io = NULL;
-	}
-}
-
-static size_t o_buffer_add(FileOBuffer *fbuf, const void *data, size_t size)
-{
-	size_t unused, sent;
-	int i;
-
-	unused = get_unused_space(fbuf);
-	if (unused < size)
-		o_buffer_grow(fbuf, size-unused);
-
-	sent = 0;
-	for (i = 0; i < 2 && sent < size && !fbuf->full; i++) {
-		unused = fbuf->tail >= fbuf->head ?
-			fbuf->buffer_size - fbuf->tail :
-			fbuf->head - fbuf->tail;
-
-		if (unused > size-sent)
-			unused = size-sent;
-		memcpy(fbuf->buffer + fbuf->tail, data, unused);
-		sent += unused;
-
-		fbuf->tail += unused;
-		if (fbuf->tail == fbuf->buffer_size)
-			fbuf->tail = 0;
-
-		if (fbuf->head == fbuf->tail)
-			fbuf->full = TRUE;
-	}
-
-	if (sent != 0 && fbuf->io == NULL && !fbuf->corked) {
-		fbuf->io = io_add_priority(fbuf->fd, fbuf->priority, IO_WRITE,
-					   buffer_send_io, fbuf);
-	}
-
-	i_assert(!BUFFER_IS_BLOCKING(fbuf) || sent == size);
-	return sent;
-}
-
-static ssize_t _send(_OBuffer *buf, const void *data, size_t size)
-{
-	FileOBuffer *fbuf = (FileOBuffer *) buf;
-	struct iovec iov;
-	ssize_t ret;
-
-	i_assert(size <= SSIZE_T_MAX);
-
-	if (buf->obuffer.closed)
-		return -1;
-
-	buf->obuffer.buf_errno = 0;
-
-	/* never try sending buffer immediately if we're block,
-	   so we don't need to deal with timeout issues here */
-	if (IS_BUFFER_EMPTY(fbuf) && !BUFFER_IS_BLOCKING(fbuf) &&
-	    (!fbuf->corked || !_have_space(buf, size))) {
-		iov.iov_base = (void *) data;
-		iov.iov_len = size;
-		ret = o_buffer_writev(fbuf, &iov, 1);
-		if (ret < 0 || (size_t)ret == size)
-			return ret;
-
-		data = (const char *) data + ret;
-		size -= ret;
-	}
-
-	if (!_have_space(buf, size) && BUFFER_IS_BLOCKING(fbuf)) {
-		/* send it blocking */
-		if (o_buffer_send_blocking(fbuf, data, size) < 0)
-			return -1;
-		return (ssize_t)size;
-	} else {
-		/* buffer it, at least partly */
-		return (ssize_t)o_buffer_add(fbuf, data, size);
-	}
-}
-
-static off_t io_buffer_sendfile(_OBuffer *outbuf, IBuffer *inbuf)
-{
-	FileOBuffer *foutbuf = (FileOBuffer *) outbuf;
-	time_t timeout_time;
-	uoff_t start_offset;
-	uoff_t offset, send_size;
-	ssize_t ret;
-	int in_fd, first;
-
-	in_fd = i_buffer_get_fd(inbuf);
-	if (in_fd == -1) {
-		outbuf->obuffer.buf_errno = EINVAL;
-		return -1;
-	}
-
-	/* set timeout time before flushing existing buffer which may block */
-	timeout_time = GET_TIMEOUT_TIME(foutbuf);
-        start_offset = inbuf->v_offset;
-
-	/* flush out any data in buffer */
-	if (buffer_flush(foutbuf) < 0)
-		return -1;
-
-	first = TRUE;
-	for (;;) {
-		if (first)
-			first = FALSE;
-		else if (timeout_time > 0 && time(NULL) > timeout_time) {
-			/* timeouted */
-			if (foutbuf->timeout_func != NULL)
-				foutbuf->timeout_func(foutbuf->timeout_context);
-			outbuf->obuffer.buf_errno = EAGAIN;
-			return -1;
-		}
-
-		offset = inbuf->start_offset + inbuf->v_offset;
-		send_size = inbuf->v_limit - inbuf->v_offset;
-
-		ret = safe_sendfile(foutbuf->fd, in_fd, &offset,
-				    MAX_SSIZE_T(send_size));
-		if (ret < 0) {
-			if (errno != EINTR && errno != EAGAIN) {
-				outbuf->obuffer.buf_errno = errno;
-				if (errno != EINVAL) {
-					/* close only if error wasn't because
-					   sendfile() isn't supported */
-					buffer_closed(foutbuf);
-				}
-				return -1;
-			}
-
-			if (!BUFFER_IS_BLOCKING(foutbuf)) {
-				/* don't block */
-				break;
-			}
-			ret = 0;
-		}
-
-		i_buffer_skip(inbuf, (size_t)ret);
-		outbuf->obuffer.offset += ret;
-
-		if ((uoff_t)ret == send_size) {
-			/* yes, all sent */
-			break;
-		}
-	}
-
-	return (off_t) (inbuf->v_offset - start_offset);
-}
-
-static off_t io_buffer_copy(_OBuffer *outbuf, IBuffer *inbuf)
-{
-	FileOBuffer *foutbuf = (FileOBuffer *) outbuf;
-	time_t timeout_time;
-	uoff_t start_offset;
-	struct iovec iov[3];
-	int iov_len;
-	const unsigned char *data;
-	size_t size;
-	ssize_t ret;
-	int pos;
-
-	timeout_time = GET_TIMEOUT_TIME(foutbuf);
-	iov_len = o_buffer_fill_iovec(foutbuf, iov);
-
-        start_offset = inbuf->v_offset;
-	for (;;) {
-		(void)i_buffer_read_data(inbuf, &data, &size,
-					 O_BUFFER_MIN_SIZE-1);
-
-		if (size == 0) {
-			/* all sent */
-			break;
-		}
-
-		pos = iov_len++;
-		iov[pos].iov_base = (void *) data;
-		iov[pos].iov_len = size;
-
-		ret = o_buffer_writev(foutbuf, iov, iov_len);
-		if (ret < 0) {
-			/* error */
-			return -1;
-		}
-
-		if (ret == 0 && !BUFFER_IS_BLOCKING(foutbuf)) {
-			/* don't block */
-			break;
-		}
-
-		if (timeout_time > 0 && time(NULL) > timeout_time) {
-			/* timeouted */
-			if (foutbuf->timeout_func != NULL)
-				foutbuf->timeout_func(foutbuf->timeout_context);
-			outbuf->obuffer.buf_errno = EAGAIN;
-			return -1;
-		}
-
-		i_buffer_skip(inbuf, size - iov[pos].iov_len);
-		iov_len--;
-
-		/* if we already sent the iov[0] and iov[1], we
-		   can just remove them from future calls */
-		while (iov_len > 0 && iov[0].iov_len == 0) {
-			iov[0] = iov[1];
-			if (iov_len > 1) iov[1] = iov[2];
-			iov_len--;
-		}
-	}
-
-	return (off_t) (inbuf->v_offset - start_offset);
-}
-
-static off_t _send_ibuffer(_OBuffer *outbuf, IBuffer *inbuf)
-{
-	off_t ret;
-
-	i_assert(inbuf->v_limit <= OFF_T_MAX);
-	i_assert(inbuf->v_offset <= inbuf->v_limit);
-
-	if (inbuf->v_offset == inbuf->v_limit)
-		return 0;
-
-	ret = io_buffer_sendfile(outbuf, inbuf);
-	if (ret >= 0 || outbuf->obuffer.buf_errno != EINVAL)
-		return ret;
-
-	/* sendfile() not supported (with this fd), fallback to
-	   regular sending */
-
-	outbuf->obuffer.buf_errno = 0;
-	return io_buffer_copy(outbuf, inbuf);
-}
-
-OBuffer *o_buffer_create_file(int fd, Pool pool, size_t max_buffer_size,
-			      int priority, int autoclose_fd)
-{
-	FileOBuffer *fbuf;
-
-	fbuf = p_new(pool, FileOBuffer, 1);
-	fbuf->fd = fd;
-	fbuf->priority = priority;
-	fbuf->max_buffer_size = max_buffer_size;
-	fbuf->autoclose_fd = autoclose_fd;
-
-	fbuf->obuf.iobuf.close = _close;
-	fbuf->obuf.iobuf.destroy = _destroy;
-	fbuf->obuf.iobuf.set_max_size = _set_max_size;
-	fbuf->obuf.iobuf.set_blocking = _set_blocking;
-
-	fbuf->obuf.cork = _cork;
-	fbuf->obuf.flush = _flush;
-	fbuf->obuf.have_space = _have_space;
-	fbuf->obuf.seek = _seek;
-	fbuf->obuf.send = _send;
-	fbuf->obuf.send_ibuffer = _send_ibuffer;
-
-	return _o_buffer_create(&fbuf->obuf, pool);
-}
--- a/src/lib/obuffer-internal.h	Fri Dec 06 00:37:33 2002 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,27 +0,0 @@
-#ifndef __OBUFFER_INTERNAL_H
-#define __OBUFFER_INTERNAL_H
-
-#include "obuffer.h"
-#include "iobuffer-internal.h"
-
-typedef struct __OBuffer _OBuffer;
-
-struct __OBuffer {
-/* inheritance: */
-	_IOBuffer iobuf;
-
-/* methods: */
-	void (*cork)(_OBuffer *buf);
-	int (*flush)(_OBuffer *buf);
-	int (*have_space)(_OBuffer *buf, size_t size);
-	int (*seek)(_OBuffer *buf, uoff_t offset);
-	ssize_t (*send)(_OBuffer *buf, const void *data, size_t size);
-	off_t (*send_ibuffer)(_OBuffer *outbuf, IBuffer *inbuf);
-
-/* data: */
-	OBuffer obuffer;
-};
-
-OBuffer *_o_buffer_create(_OBuffer *_buf, Pool pool);
-
-#endif
--- a/src/lib/obuffer.c	Fri Dec 06 00:37:33 2002 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,124 +0,0 @@
-/*
-   obuffer.c : Output buffer handling
-
-    Copyright (c) 2002 Timo Sirainen
-
-    Permission is hereby granted, free of charge, to any person obtaining
-    a copy of this software and associated documentation files (the
-    "Software"), to deal in the Software without restriction, including
-    without limitation the rights to use, copy, modify, merge, publish,
-    distribute, sublicense, and/or sell copies of the Software, and to
-    permit persons to whom the Software is furnished to do so, subject to
-    the following conditions:
-
-    The above copyright notice and this permission notice shall be
-    included in all copies or substantial portions of the Software.
-
-    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-    TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-    SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-*/
-
-#include "lib.h"
-#include "ibuffer.h"
-#include "obuffer-internal.h"
-
-void o_buffer_ref(OBuffer *buf)
-{
-	_io_buffer_ref(buf->real_buffer);
-}
-
-void o_buffer_unref(OBuffer *buf)
-{
-	_io_buffer_unref(buf->real_buffer);
-}
-
-void o_buffer_close(OBuffer *buf)
-{
-	_io_buffer_close(buf->real_buffer);
-	buf->closed = TRUE;
-}
-
-void o_buffer_set_max_size(OBuffer *buf, size_t max_size)
-{
-	_io_buffer_set_max_size(buf->real_buffer, max_size);
-}
-
-void o_buffer_set_blocking(OBuffer *buf, int timeout_msecs,
-			   void (*timeout_func)(void *), void *context)
-{
-	_io_buffer_set_blocking(buf->real_buffer, timeout_msecs,
-				timeout_func, context);
-}
-
-void o_buffer_cork(OBuffer *buf)
-{
-	_OBuffer *_buf = buf->real_buffer;
-
-	if (buf->closed)
-		return;
-
-	_buf->cork(_buf);
-}
-
-int o_buffer_flush(OBuffer *buf)
-{
-	_OBuffer *_buf = buf->real_buffer;
-
-	if (buf->closed)
-		return -1;
-
-	return _buf->flush(_buf);
-}
-
-int o_buffer_have_space(OBuffer *buf, size_t size)
-{
-	_OBuffer *_buf = buf->real_buffer;
-
-	return _buf->have_space(_buf, size);
-}
-
-int o_buffer_seek(OBuffer *buf, uoff_t offset)
-{
-	_OBuffer *_buf = buf->real_buffer;
-
-	if (buf->closed)
-		return -1;
-
-	return _buf->seek(_buf, offset);
-}
-
-ssize_t o_buffer_send(OBuffer *buf, const void *data, size_t size)
-{
-	_OBuffer *_buf = buf->real_buffer;
-
-	if (buf->closed)
-		return -1;
-
-	if (size == 0)
-		return 0;
-
-	return _buf->send(_buf, data, size);
-}
-
-off_t o_buffer_send_ibuffer(OBuffer *outbuf, IBuffer *inbuf)
-{
-	_OBuffer *_outbuf = outbuf->real_buffer;
-
-	if (outbuf->closed || inbuf->closed)
-		return -1;
-
-	return _outbuf->send_ibuffer(_outbuf, inbuf);
-}
-
-OBuffer *_o_buffer_create(_OBuffer *_buf, Pool pool)
-{
-	_buf->obuffer.real_buffer = _buf;
-
-	_io_buffer_init(pool, &_buf->iobuf);
-	return &_buf->obuffer;
-}
--- a/src/lib/obuffer.h	Fri Dec 06 00:37:33 2002 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +0,0 @@
-#ifndef __OBUFFER_H
-#define __OBUFFER_H
-
-struct _OBuffer {
-	uoff_t offset;
-
-	int buf_errno;
-	unsigned int closed:1;
-
-	void *real_buffer;
-};
-
-OBuffer *o_buffer_create_file(int fd, Pool pool, size_t max_buffer_size,
-			      int priority, int autoclose_fd);
-
-/* Reference counting. References start from 1, so calling o_buffer_unref()
-   destroys the buffer if o_buffer_ref() is never used. */
-void o_buffer_ref(OBuffer *buf);
-void o_buffer_unref(OBuffer *buf);
-
-/* Mark the buffer closed. Nothing will be sent after this call. */
-void o_buffer_close(OBuffer *buf);
-
-/* Change the maximum size for buffer to grow. */
-void o_buffer_set_max_size(OBuffer *buf, size_t max_size);
-/* Buffer is made to be flushed out whenever it gets full (assumes max_size
-   is already set), ie. writes will never be partial. Also makes any blocking
-   writes to fail after specified timeout, calling timeout_func if it's
-   set. This call changes non-blocking state of file descriptor. */
-void o_buffer_set_blocking(OBuffer *buf, int timeout_msecs,
-			   void (*timeout_func)(void *), void *context);
-
-/* Delays sending as far as possible, writing only full buffers. Also sets
-   TCP_CORK on if supported. o_buffer_flush() removes the cork. */
-void o_buffer_cork(OBuffer *buf);
-/* Flush the output buffer, blocks until everything is sent.
-   Returns 1 if ok, -1 if error. */
-int o_buffer_flush(OBuffer *buf);
-/* Returns 1 if specified amount of data fits into buffer before reaching
-   max_size, 0 if not. */
-int o_buffer_have_space(OBuffer *buf, size_t size);
-
-/* Seek to specified position from beginning of file. This works only for
-   files. Returns 1 if successful, -1 if error. */
-int o_buffer_seek(OBuffer *buf, uoff_t offset);
-/* Returns number of bytes sent or buffered, or -1 if disconnected */
-ssize_t o_buffer_send(OBuffer *buf, const void *data, size_t size);
-/* Send data from input buffer to output buffer using the fastest
-   possible method. Returns number of bytes sent, or -1 if error.
-   Note that this function may block if either inbuf or outbuf is blocking. */
-off_t o_buffer_send_ibuffer(OBuffer *outbuf, IBuffer *inbuf);
-
-#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib/ostream-file.c	Fri Dec 06 03:09:22 2002 +0200
@@ -0,0 +1,684 @@
+/*
+   ostream-file.c : Output stream handling for files
+
+    Copyright (c) 2002 Timo Sirainen
+
+    Permission is hereby granted, free of charge, to any person obtaining
+    a copy of this software and associated documentation files (the
+    "Software"), to deal in the Software without restriction, including
+    without limitation the rights to use, copy, modify, merge, publish,
+    distribute, sublicense, and/or sell copies of the Software, and to
+    permit persons to whom the Software is furnished to do so, subject to
+    the following conditions:
+
+    The above copyright notice and this permission notice shall be
+    included in all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+    TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+    SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include "lib.h"
+#include "alarm-hup.h"
+#include "ioloop.h"
+#include "network.h"
+#include "sendfile-util.h"
+#include "istream.h"
+#include "ostream-internal.h"
+
+#include <unistd.h>
+#ifdef HAVE_SYS_UIO_H
+#  include <sys/uio.h>
+#endif
+
+#define O_STREAM_MIN_SIZE 4096
+
+#define IS_STREAM_EMPTY(fstream) \
+	(!(fstream)->full && (fstream)->head == (fstream)->tail)
+
+#define MAX_SSIZE_T(size) \
+	((size) < SSIZE_T_MAX ? (size_t)(size) : SSIZE_T_MAX)
+
+typedef struct {
+	_OStream ostream;
+
+	int fd;
+	int priority;
+	IO io;
+
+	unsigned char *buffer; /* ring-buffer */
+	size_t buffer_size, max_buffer_size;
+	size_t head, tail; /* first unsent/unused byte */
+
+	int timeout_msecs;
+	void (*timeout_func)(void *);
+	void *timeout_context;
+
+	unsigned int full:1; /* if head == tail, is buffer empty or full? */
+	unsigned int corked:1;
+	unsigned int no_socket_cork:1;
+	unsigned int autoclose_fd:1;
+} FileOStream;
+
+static void stream_closed(FileOStream *fstream)
+{
+	if (fstream->autoclose_fd && fstream->fd != -1) {
+		if (close(fstream->fd) < 0)
+			i_error("FileOStream.close() failed: %m");
+		fstream->fd = -1;
+	}
+
+	if (fstream->io != NULL) {
+		io_remove(fstream->io);
+		fstream->io = NULL;
+	}
+
+	fstream->ostream.ostream.closed = TRUE;
+}
+
+static void _close(_IOStream *stream)
+{
+	FileOStream *fstream = (FileOStream *) stream;
+
+	/* flush output before really closing it */
+	o_stream_flush(&fstream->ostream.ostream);
+
+	stream_closed(fstream);
+}
+
+static void _destroy(_IOStream *stream)
+{
+	FileOStream *fstream = (FileOStream *) stream;
+
+	p_free(fstream->ostream.iostream.pool, fstream->buffer);
+}
+
+static void _set_max_buffer_size(_IOStream *stream, size_t max_size)
+{
+	FileOStream *fstream = (FileOStream *) stream;
+
+	fstream->max_buffer_size = max_size;
+}
+
+static void _set_blocking(_IOStream *stream, int timeout_msecs,
+			  void (*timeout_func)(void *), void *context)
+{
+	FileOStream *fstream = (FileOStream *) stream;
+
+	fstream->timeout_msecs = timeout_msecs;
+	fstream->timeout_func = timeout_func;
+	fstream->timeout_context = context;
+
+	net_set_nonblock(fstream->fd, timeout_msecs == 0);
+
+	if (timeout_msecs != 0)
+		alarm_hup_init();
+}
+
+static void _cork(_OStream *stream)
+{
+	FileOStream *fstream = (FileOStream *) stream;
+
+	if (!fstream->corked) {
+		if (!fstream->no_socket_cork) {
+			if (net_set_cork(fstream->fd, TRUE) < 0)
+				fstream->no_socket_cork = TRUE;
+		}
+		fstream->corked = TRUE;
+	}
+}
+
+static void update_iovec(struct iovec *iov, unsigned int iov_size, size_t size)
+{
+	while (size > 0) {
+		i_assert(iov_size > 0);
+
+		if ((size_t)iov->iov_len <= size) {
+			size -= iov->iov_len;
+			iov->iov_base = NULL;
+			iov->iov_len = 0;
+		} else {
+			iov->iov_base = (char *) iov->iov_base + size;
+			iov->iov_len -= size;
+			size = 0;
+		}
+		iov++; iov_size--;
+	}
+}
+
+static void update_buffer(FileOStream *fstream, size_t size)
+{
+	size_t used;
+
+	if (IS_STREAM_EMPTY(fstream))
+		return;
+
+	if (fstream->head < fstream->tail) {
+		/* ...HXXXT... */
+		used = fstream->tail - fstream->head;
+		fstream->head += I_MIN(used, size);
+	} else {
+		/* XXXT...HXXX */
+		used = fstream->buffer_size - fstream->head;
+		if (size > used) {
+			size -= used;
+			if (size < fstream->tail)
+				fstream->head = size;
+			else {
+				/* whole buffer is sent */
+				fstream->head = fstream->tail = 0;
+			}
+		} else {
+			fstream->head += I_MIN(used, size);
+		}
+
+		fstream->full = FALSE;
+	}
+
+	if (fstream->head == fstream->tail)
+		fstream->head = fstream->tail = 0;
+
+	if (fstream->head == fstream->buffer_size)
+		fstream->head = 0;
+}
+
+/* NOTE: modifies iov */
+static ssize_t
+o_stream_writev(FileOStream *fstream, struct iovec *iov, int iov_size)
+{
+	ssize_t ret;
+
+	while (iov->iov_len == 0 && iov_size > 0) {
+		iov++;
+		iov_size--;
+	}
+
+	i_assert(iov_size > 0);
+
+	ret = writev(fstream->fd, iov, iov_size);
+	if (ret < 0) {
+		if (errno == EAGAIN || errno == EINTR)
+			return 0;
+		stream_closed(fstream);
+		return -1;
+	}
+
+	update_iovec(iov, iov_size, ret);
+	update_buffer(fstream, ret);
+	fstream->ostream.ostream.offset += ret;
+
+	return ret;
+}
+
+/* returns how much of vector was used */
+static int o_stream_fill_iovec(FileOStream *fstream, struct iovec iov[2])
+{
+	if (IS_STREAM_EMPTY(fstream))
+		return 0;
+
+	if (fstream->head < fstream->tail) {
+		iov[0].iov_base = fstream->buffer + fstream->head;
+		iov[0].iov_len = fstream->tail - fstream->head;
+		return 1;
+	} else {
+		iov[0].iov_base = fstream->buffer + fstream->head;
+		iov[0].iov_len = fstream->buffer_size - fstream->head;
+		if (fstream->tail == 0)
+			return 1;
+		else {
+			iov[1].iov_base = fstream->buffer;
+			iov[1].iov_len = fstream->tail;
+			return 2;
+		}
+	}
+}
+
+static int o_stream_send_blocking(FileOStream *fstream, const void *data,
+				  size_t size)
+{
+	time_t timeout_time;
+	struct iovec iov[3];
+	int iov_len, first;
+
+	iov_len = o_stream_fill_iovec(fstream, iov);
+	if (size > 0) {
+		iov[iov_len].iov_base = (void *) data;
+		iov[iov_len].iov_len = size;
+		iov_len++;
+	}
+
+	first = TRUE;
+
+	timeout_time = GET_TIMEOUT_TIME(fstream);
+	while (iov[iov_len-1].iov_len != 0) {
+		if (first)
+			first = FALSE;
+		else if (timeout_time > 0 && time(NULL) > timeout_time) {
+			/* timeouted */
+			if (fstream->timeout_func != NULL)
+				fstream->timeout_func(fstream->timeout_context);
+			fstream->ostream.ostream.stream_errno = EAGAIN;
+			return -1;
+		}
+
+		if (o_stream_writev(fstream, iov, iov_len) < 0)
+			return -1;
+	}
+
+        return 1;
+}
+
+static int buffer_flush(FileOStream *fstream)
+{
+	struct iovec iov[2];
+	int iov_len;
+
+	if (!IS_STREAM_EMPTY(fstream)) {
+		iov_len = o_stream_fill_iovec(fstream, iov);
+		if (o_stream_writev(fstream, iov, iov_len) < 0)
+			return -1;
+
+		if (!IS_STREAM_EMPTY(fstream)) {
+			if (o_stream_send_blocking(fstream, NULL, 0) < 0)
+				return -1;
+		}
+	}
+
+	return 1;
+}
+
+static int _flush(_OStream *stream)
+{
+	FileOStream *fstream = (FileOStream *) stream;
+	int ret;
+
+	ret = buffer_flush(fstream);
+
+	if (fstream->corked) {
+		/* remove cork */
+		if (!fstream->no_socket_cork) {
+			if (net_set_cork(fstream->fd, FALSE) < 0)
+				i_error("net_set_cork() failed: %m");
+		}
+		fstream->corked = FALSE;
+	}
+
+	return ret;
+}
+
+static size_t get_unused_space(FileOStream *fstream)
+{
+	if (fstream->head > fstream->tail) {
+		/* XXXT...HXXX */
+		return fstream->head - fstream->tail;
+	} else if (fstream->head < fstream->tail) {
+		/* ...HXXXT... */
+		return (fstream->buffer_size - fstream->tail) + fstream->head;
+	} else {
+		/* either fully unused or fully used */
+		return fstream->full ? 0 : fstream->buffer_size;
+	}
+}
+
+static int _have_space(_OStream *stream, size_t size)
+{
+	FileOStream *fstream = (FileOStream *) stream;
+	size_t unused;
+
+	if (fstream->max_buffer_size == 0)
+		return 1;
+
+	unused = get_unused_space(fstream);
+	if (size <= unused)
+		return 1;
+
+	unused += (fstream->max_buffer_size - fstream->buffer_size);
+	return size <= unused ? 1 : 0;
+}
+
+static int _seek(_OStream *stream, uoff_t offset)
+{
+	FileOStream *fstream = (FileOStream *) stream;
+	off_t ret;
+
+	if (offset > OFF_T_MAX) {
+		stream->ostream.stream_errno = EINVAL;
+		return -1;
+	}
+
+	ret = lseek(fstream->fd, (off_t)offset, SEEK_SET);
+	if (ret < 0) {
+		stream->ostream.stream_errno = errno;
+		return -1;
+	}
+
+	if (ret != (off_t)offset) {
+		stream->ostream.stream_errno = EINVAL;
+		return -1;
+	}
+
+	stream->ostream.stream_errno = 0;
+	stream->ostream.offset = offset;
+	return 1;
+}
+
+static void o_stream_grow_buffer(FileOStream *fstream, size_t bytes)
+{
+	size_t size, head_size;
+
+	size = nearest_power(fstream->buffer_size + bytes);
+	if (fstream->max_buffer_size != 0) {
+		if (size > fstream->max_buffer_size) {
+			/* limit the size */
+			size = fstream->max_buffer_size;
+		} else if (fstream->corked) {
+			/* use the largest possible buffer with corking */
+			size = fstream->max_buffer_size;
+		}
+	}
+
+	if (size == fstream->buffer_size)
+		return;
+
+	fstream->buffer = p_realloc(fstream->ostream.iostream.pool,
+				    fstream->buffer, size);
+
+	if (fstream->tail <= fstream->head && !IS_STREAM_EMPTY(fstream)) {
+		head_size = I_MIN(fstream->head, size - fstream->buffer_size);
+		memcpy(fstream->buffer + fstream->buffer_size, fstream->buffer,
+		       head_size);
+
+		if (head_size == fstream->head)
+			fstream->tail = fstream->buffer_size + head_size;
+		else {
+			memmove(fstream->buffer, fstream->buffer + head_size,
+				fstream->head - head_size);
+			fstream->tail = fstream->head - head_size;
+		}
+	}
+
+	fstream->full = FALSE;
+	fstream->buffer_size = size;
+}
+
+static void stream_send_io(void *context, int fd __attr_unused__,
+			   IO io __attr_unused__)
+{
+	FileOStream *fstream = context;
+	struct iovec iov[2];
+	int iov_len;
+
+	iov_len = o_stream_fill_iovec(fstream, iov);
+
+	if (iov_len == 0 || o_stream_writev(fstream, iov, iov_len) < 0 ||
+	    iov[iov_len-1].iov_len == 0) {
+		/* error / all sent */
+		io_remove(fstream->io);
+                fstream->io = NULL;
+	}
+}
+
+static size_t o_stream_add(FileOStream *fstream, const void *data, size_t size)
+{
+	size_t unused, sent;
+	int i;
+
+	unused = get_unused_space(fstream);
+	if (unused < size)
+		o_stream_grow_buffer(fstream, size-unused);
+
+	sent = 0;
+	for (i = 0; i < 2 && sent < size && !fstream->full; i++) {
+		unused = fstream->tail >= fstream->head ?
+			fstream->buffer_size - fstream->tail :
+			fstream->head - fstream->tail;
+
+		if (unused > size-sent)
+			unused = size-sent;
+		memcpy(fstream->buffer + fstream->tail, data, unused);
+		sent += unused;
+
+		fstream->tail += unused;
+		if (fstream->tail == fstream->buffer_size)
+			fstream->tail = 0;
+
+		if (fstream->head == fstream->tail)
+			fstream->full = TRUE;
+	}
+
+	if (sent != 0 && fstream->io == NULL && !fstream->corked) {
+		fstream->io = io_add_priority(fstream->fd, fstream->priority,
+					      IO_WRITE, stream_send_io,
+					      fstream);
+	}
+
+	i_assert(!STREAM_IS_BLOCKING(fstream) || sent == size);
+	return sent;
+}
+
+static ssize_t _send(_OStream *stream, const void *data, size_t size)
+{
+	FileOStream *fstream = (FileOStream *) stream;
+	struct iovec iov;
+	ssize_t ret;
+
+	i_assert(size <= SSIZE_T_MAX);
+
+	if (stream->ostream.closed)
+		return -1;
+
+	stream->ostream.stream_errno = 0;
+
+	/* never try sending immediately if fd is blocking,
+	   so we don't need to deal with timeout issues here */
+	if (IS_STREAM_EMPTY(fstream) && !STREAM_IS_BLOCKING(fstream) &&
+	    (!fstream->corked || !_have_space(stream, size))) {
+		iov.iov_base = (void *) data;
+		iov.iov_len = size;
+		ret = o_stream_writev(fstream, &iov, 1);
+		if (ret < 0 || (size_t)ret == size)
+			return ret;
+
+		data = (const char *) data + ret;
+		size -= ret;
+	}
+
+	if (!_have_space(stream, size) && STREAM_IS_BLOCKING(fstream)) {
+		/* send it blocking */
+		if (o_stream_send_blocking(fstream, data, size) < 0)
+			return -1;
+		return (ssize_t)size;
+	} else {
+		/* buffer it, at least partly */
+		return (ssize_t)o_stream_add(fstream, data, size);
+	}
+}
+
+static off_t io_stream_sendfile(_OStream *outstream, IStream *instream)
+{
+	FileOStream *foutstream = (FileOStream *) outstream;
+	time_t timeout_time;
+	uoff_t start_offset;
+	uoff_t offset, send_size;
+	ssize_t ret;
+	int in_fd, first;
+
+	in_fd = i_stream_get_fd(instream);
+	if (in_fd == -1) {
+		outstream->ostream.stream_errno = EINVAL;
+		return -1;
+	}
+
+	/* set timeout time before flushing existing buffer which may block */
+	timeout_time = GET_TIMEOUT_TIME(foutstream);
+        start_offset = instream->v_offset;
+
+	/* flush out any data in buffer */
+	if (buffer_flush(foutstream) < 0)
+		return -1;
+
+	first = TRUE;
+	for (;;) {
+		if (first)
+			first = FALSE;
+		else if (timeout_time > 0 && time(NULL) > timeout_time) {
+			/* timeouted */
+			if (foutstream->timeout_func != NULL) {
+				foutstream->timeout_func(
+					foutstream->timeout_context);
+			}
+			outstream->ostream.stream_errno = EAGAIN;
+			return -1;
+		}
+
+		offset = instream->start_offset + instream->v_offset;
+		send_size = instream->v_limit - instream->v_offset;
+
+		ret = safe_sendfile(foutstream->fd, in_fd, &offset,
+				    MAX_SSIZE_T(send_size));
+		if (ret < 0) {
+			if (errno != EINTR && errno != EAGAIN) {
+				outstream->ostream.stream_errno = errno;
+				if (errno != EINVAL) {
+					/* close only if error wasn't because
+					   sendfile() isn't supported */
+					stream_closed(foutstream);
+				}
+				return -1;
+			}
+
+			if (!STREAM_IS_BLOCKING(foutstream)) {
+				/* don't block */
+				break;
+			}
+			ret = 0;
+		}
+
+		i_stream_skip(instream, (size_t)ret);
+		outstream->ostream.offset += ret;
+
+		if ((uoff_t)ret == send_size) {
+			/* yes, all sent */
+			break;
+		}
+	}
+
+	return (off_t) (instream->v_offset - start_offset);
+}
+
+static off_t io_stream_copy(_OStream *outstream, IStream *instream)
+{
+	FileOStream *foutstream = (FileOStream *) outstream;
+	time_t timeout_time;
+	uoff_t start_offset;
+	struct iovec iov[3];
+	int iov_len;
+	const unsigned char *data;
+	size_t size;
+	ssize_t ret;
+	int pos;
+
+	timeout_time = GET_TIMEOUT_TIME(foutstream);
+	iov_len = o_stream_fill_iovec(foutstream, iov);
+
+        start_offset = instream->v_offset;
+	for (;;) {
+		(void)i_stream_read_data(instream, &data, &size,
+					 O_STREAM_MIN_SIZE-1);
+
+		if (size == 0) {
+			/* all sent */
+			break;
+		}
+
+		pos = iov_len++;
+		iov[pos].iov_base = (void *) data;
+		iov[pos].iov_len = size;
+
+		ret = o_stream_writev(foutstream, iov, iov_len);
+		if (ret < 0) {
+			/* error */
+			return -1;
+		}
+
+		if (ret == 0 && !STREAM_IS_BLOCKING(foutstream)) {
+			/* don't block */
+			break;
+		}
+
+		if (timeout_time > 0 && time(NULL) > timeout_time) {
+			/* timeouted */
+			if (foutstream->timeout_func != NULL) {
+				foutstream->timeout_func(
+					foutstream->timeout_context);
+			}
+			outstream->ostream.stream_errno = EAGAIN;
+			return -1;
+		}
+
+		i_stream_skip(instream, size - iov[pos].iov_len);
+		iov_len--;
+
+		/* if we already sent the iov[0] and iov[1], we
+		   can just remove them from future calls */
+		while (iov_len > 0 && iov[0].iov_len == 0) {
+			iov[0] = iov[1];
+			if (iov_len > 1) iov[1] = iov[2];
+			iov_len--;
+		}
+	}
+
+	return (off_t) (instream->v_offset - start_offset);
+}
+
+static off_t _send_istream(_OStream *outstream, IStream *instream)
+{
+	off_t ret;
+
+	i_assert(instream->v_limit <= OFF_T_MAX);
+	i_assert(instream->v_offset <= instream->v_limit);
+
+	if (instream->v_offset == instream->v_limit)
+		return 0;
+
+	ret = io_stream_sendfile(outstream, instream);
+	if (ret >= 0 || outstream->ostream.stream_errno != EINVAL)
+		return ret;
+
+	/* sendfile() not supported (with this fd), fallback to
+	   regular sending */
+
+	outstream->ostream.stream_errno = 0;
+	return io_stream_copy(outstream, instream);
+}
+
+OStream *o_stream_create_file(int fd, Pool pool, size_t max_buffer_size,
+			      int priority, int autoclose_fd)
+{
+	FileOStream *fstream;
+
+	fstream = p_new(pool, FileOStream, 1);
+	fstream->fd = fd;
+	fstream->priority = priority;
+	fstream->max_buffer_size = max_buffer_size;
+	fstream->autoclose_fd = autoclose_fd;
+
+	fstream->ostream.iostream.close = _close;
+	fstream->ostream.iostream.destroy = _destroy;
+	fstream->ostream.iostream.set_max_buffer_size = _set_max_buffer_size;
+	fstream->ostream.iostream.set_blocking = _set_blocking;
+
+	fstream->ostream.cork = _cork;
+	fstream->ostream.flush = _flush;
+	fstream->ostream.have_space = _have_space;
+	fstream->ostream.seek = _seek;
+	fstream->ostream.send = _send;
+	fstream->ostream.send_istream = _send_istream;
+
+	return _o_stream_create(&fstream->ostream, pool);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib/ostream-internal.h	Fri Dec 06 03:09:22 2002 +0200
@@ -0,0 +1,27 @@
+#ifndef __OSTREAM_INTERNAL_H
+#define __OSTREAM_INTERNAL_H
+
+#include "ostream.h"
+#include "iostream-internal.h"
+
+typedef struct __OStream _OStream;
+
+struct __OStream {
+/* inheritance: */
+	_IOStream iostream;
+
+/* methods: */
+	void (*cork)(_OStream *stream);
+	int (*flush)(_OStream *stream);
+	int (*have_space)(_OStream *stream, size_t size);
+	int (*seek)(_OStream *stream, uoff_t offset);
+	ssize_t (*send)(_OStream *stream, const void *data, size_t size);
+	off_t (*send_istream)(_OStream *outstream, IStream *instream);
+
+/* data: */
+	OStream ostream;
+};
+
+OStream *_o_stream_create(_OStream *_stream, Pool pool);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib/ostream.c	Fri Dec 06 03:09:22 2002 +0200
@@ -0,0 +1,124 @@
+/*
+   ostream.c : Output stream handling
+
+    Copyright (c) 2002 Timo Sirainen
+
+    Permission is hereby granted, free of charge, to any person obtaining
+    a copy of this software and associated documentation files (the
+    "Software"), to deal in the Software without restriction, including
+    without limitation the rights to use, copy, modify, merge, publish,
+    distribute, sublicense, and/or sell copies of the Software, and to
+    permit persons to whom the Software is furnished to do so, subject to
+    the following conditions:
+
+    The above copyright notice and this permission notice shall be
+    included in all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+    TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+    SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include "lib.h"
+#include "istream.h"
+#include "ostream-internal.h"
+
+void o_stream_ref(OStream *stream)
+{
+	_io_stream_ref(stream->real_stream);
+}
+
+void o_stream_unref(OStream *stream)
+{
+	_io_stream_unref(stream->real_stream);
+}
+
+void o_stream_close(OStream *stream)
+{
+	_io_stream_close(stream->real_stream);
+	stream->closed = TRUE;
+}
+
+void o_stream_set_max_buffer_size(OStream *stream, size_t max_size)
+{
+	_io_stream_set_max_buffer_size(stream->real_stream, max_size);
+}
+
+void o_stream_set_blocking(OStream *stream, int timeout_msecs,
+			   void (*timeout_func)(void *), void *context)
+{
+	_io_stream_set_blocking(stream->real_stream, timeout_msecs,
+				timeout_func, context);
+}
+
+void o_stream_cork(OStream *stream)
+{
+	_OStream *_stream = stream->real_stream;
+
+	if (stream->closed)
+		return;
+
+	_stream->cork(_stream);
+}
+
+int o_stream_flush(OStream *stream)
+{
+	_OStream *_stream = stream->real_stream;
+
+	if (stream->closed)
+		return -1;
+
+	return _stream->flush(_stream);
+}
+
+int o_stream_have_space(OStream *stream, size_t size)
+{
+	_OStream *_stream = stream->real_stream;
+
+	return _stream->have_space(_stream, size);
+}
+
+int o_stream_seek(OStream *stream, uoff_t offset)
+{
+	_OStream *_stream = stream->real_stream;
+
+	if (stream->closed)
+		return -1;
+
+	return _stream->seek(_stream, offset);
+}
+
+ssize_t o_stream_send(OStream *stream, const void *data, size_t size)
+{
+	_OStream *_stream = stream->real_stream;
+
+	if (stream->closed)
+		return -1;
+
+	if (size == 0)
+		return 0;
+
+	return _stream->send(_stream, data, size);
+}
+
+off_t o_stream_send_istream(OStream *outstream, IStream *instream)
+{
+	_OStream *_outstream = outstream->real_stream;
+
+	if (outstream->closed || instream->closed)
+		return -1;
+
+	return _outstream->send_istream(_outstream, instream);
+}
+
+OStream *_o_stream_create(_OStream *_stream, Pool pool)
+{
+	_stream->ostream.real_stream = _stream;
+
+	_io_stream_init(pool, &_stream->iostream);
+	return &_stream->ostream;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib/ostream.h	Fri Dec 06 03:09:22 2002 +0200
@@ -0,0 +1,53 @@
+#ifndef __OSTREAM_H
+#define __OSTREAM_H
+
+struct _OStream {
+	uoff_t offset;
+
+	int stream_errno;
+	unsigned int closed:1;
+
+	void *real_stream;
+};
+
+OStream *o_stream_create_file(int fd, Pool pool, size_t max_buffer_size,
+			      int priority, int autoclose_fd);
+
+/* Reference counting. References start from 1, so calling o_stream_unref()
+   destroys the stream if o_stream_ref() is never used. */
+void o_stream_ref(OStream *stream);
+void o_stream_unref(OStream *stream);
+
+/* Mark the stream closed. Nothing will be sent after this call. */
+void o_stream_close(OStream *stream);
+
+/* Change the maximum size for stream's output buffer to grow. */
+void o_stream_set_max_buffer_size(OStream *stream, size_t max_size);
+/* Stream is made to be flushed out whenever it gets full (assumes max_size
+   is already set), ie. writes will never be partial. Also makes any blocking
+   writes to fail after specified timeout, calling timeout_func if it's
+   set. This call changes non-blocking state of file descriptor. */
+void o_stream_set_blocking(OStream *stream, int timeout_msecs,
+			   void (*timeout_func)(void *), void *context);
+
+/* Delays sending as far as possible, writing only full buffers. Also sets
+   TCP_CORK on if supported. o_stream_flush() removes the cork. */
+void o_stream_cork(OStream *stream);
+/* Flush the output stream, blocks until everything is sent.
+   Returns 1 if ok, -1 if error. */
+int o_stream_flush(OStream *stream);
+/* Returns 1 if specified amount of data currently fits into stream's output
+   buffer, 0 if not. */
+int o_stream_have_space(OStream *stream, size_t size);
+
+/* Seek to specified position from beginning of file. This works only for
+   files. Returns 1 if successful, -1 if error. */
+int o_stream_seek(OStream *stream, uoff_t offset);
+/* Returns number of bytes sent or buffered, or -1 if disconnected */
+ssize_t o_stream_send(OStream *stream, const void *data, size_t size);
+/* Send data from input stream. Returns number of bytes sent, or -1 if error.
+   Note that this function may block if either instream or outstream is
+   blocking. */
+off_t o_stream_send_istream(OStream *outstream, IStream *instream);
+
+#endif
--- a/src/login/auth-connection.c	Fri Dec 06 00:37:33 2002 +0200
+++ b/src/login/auth-connection.c	Fri Dec 06 03:09:22 2002 +0200
@@ -4,8 +4,8 @@
 #include "hash.h"
 #include "ioloop.h"
 #include "network.h"
-#include "ibuffer.h"
-#include "obuffer.h"
+#include "istream.h"
+#include "ostream.h"
 #include "auth-connection.h"
 
 #include <unistd.h>
@@ -22,8 +22,8 @@
 	char *path;
 	int fd;
 	IO io;
-	IBuffer *inbuf;
-	OBuffer *outbuf;
+	IStream *input;
+	OStream *output;
 
 	int auth_process;
 	AuthMethod available_auth_methods;
@@ -73,9 +73,9 @@
 	conn->path = i_strdup(path);
 	conn->fd = fd;
 	conn->io = io_add(fd, IO_READ, auth_input, conn);
-	conn->inbuf = i_buffer_create_file(fd, default_pool, MAX_INBUF_SIZE,
+	conn->input = i_stream_create_file(fd, default_pool, MAX_INBUF_SIZE,
 					   FALSE);
-	conn->outbuf = o_buffer_create_file(fd, default_pool, MAX_OUTBUF_SIZE,
+	conn->output = o_stream_create_file(fd, default_pool, MAX_OUTBUF_SIZE,
 					    IO_PRIORITY_DEFAULT, FALSE);
 	conn->requests = hash_create(default_pool, 100, NULL, NULL);
 
@@ -121,8 +121,8 @@
 
 	(void)close(conn->fd);
 	io_remove(conn->io);
-	i_buffer_unref(conn->inbuf);
-	o_buffer_unref(conn->outbuf);
+	i_stream_unref(conn->input);
+	o_stream_unref(conn->output);
 	i_free(conn->path);
 	i_free(conn);
 }
@@ -136,7 +136,7 @@
 	found = FALSE;
 	for (conn = auth_connections; conn != NULL; conn = conn->next) {
 		if ((conn->available_auth_methods & method)) {
-			if (o_buffer_have_space(conn->outbuf, size) > 0)
+			if (o_stream_have_space(conn->output, size) > 0)
 				return conn;
 
 			found = TRUE;
@@ -210,7 +210,7 @@
 	const unsigned char *data;
 	size_t size;
 
-	switch (i_buffer_read(conn->inbuf)) {
+	switch (i_stream_read(conn->input)) {
 	case 0:
 		return;
 	case -1:
@@ -226,12 +226,12 @@
 		return;
 	}
 
-	data = i_buffer_get_data(conn->inbuf, &size);
+	data = i_stream_get_data(conn->input, &size);
 
 	if (!conn->init_received) {
 		if (size == sizeof(AuthInitData)) {
 			memcpy(&init_data, data, sizeof(AuthInitData));
-			i_buffer_skip(conn->inbuf, sizeof(AuthInitData));
+			i_stream_skip(conn->input, sizeof(AuthInitData));
 
 			auth_handle_init(conn, &init_data);
 		} else if (size > sizeof(AuthInitData)) {
@@ -245,14 +245,14 @@
 	}
 
 	if (!conn->in_reply_received) {
-		data = i_buffer_get_data(conn->inbuf, &size);
+		data = i_stream_get_data(conn->input, &size);
 		if (size < sizeof(AuthReplyData))
 			return;
 
 		memcpy(&conn->in_reply, data, sizeof(AuthReplyData));
 		data += sizeof(AuthReplyData);
 		size -= sizeof(AuthReplyData);
-		i_buffer_skip(conn->inbuf, sizeof(AuthReplyData));
+		i_stream_skip(conn->input, sizeof(AuthReplyData));
 		conn->in_reply_received = TRUE;
 	}
 
@@ -262,7 +262,7 @@
 	/* we've got a full reply */
 	conn->in_reply_received = FALSE;
 	auth_handle_reply(conn, &conn->in_reply, data);
-	i_buffer_skip(conn->inbuf, conn->in_reply.data_size);
+	i_stream_skip(conn->input, conn->in_reply.data_size);
 }
 
 int auth_init_request(AuthMethod method, AuthCallback callback,
@@ -293,7 +293,7 @@
 	request_data.type = AUTH_REQUEST_INIT;
 	request_data.method = request->method;
 	request_data.id = request->id;
-	if (o_buffer_send(request->conn->outbuf, &request_data,
+	if (o_stream_send(request->conn->output, &request_data,
 			  sizeof(request_data)) < 0)
 		auth_connection_destroy(request->conn);
 	return TRUE;
@@ -310,10 +310,10 @@
 	request_data.id = request->id;
 	request_data.data_size = data_size;
 
-	if (o_buffer_send(request->conn->outbuf, &request_data,
+	if (o_stream_send(request->conn->output, &request_data,
 			  sizeof(request_data)) < 0)
 		auth_connection_destroy(request->conn);
-	else if (o_buffer_send(request->conn->outbuf, data, data_size) < 0)
+	else if (o_stream_send(request->conn->output, data, data_size) < 0)
 		auth_connection_destroy(request->conn);
 }
 
--- a/src/login/client-authenticate.c	Fri Dec 06 00:37:33 2002 +0200
+++ b/src/login/client-authenticate.c	Fri Dec 06 03:09:22 2002 +0200
@@ -3,8 +3,8 @@
 #include "common.h"
 #include "base64.h"
 #include "ioloop.h"
-#include "ibuffer.h"
-#include "obuffer.h"
+#include "istream.h"
+#include "ostream.h"
 #include "temp-string.h"
 #include "auth-connection.h"
 #include "client.h"
@@ -73,7 +73,7 @@
 
 	client_send_tagline(client, msg != NULL ? msg :
 			    "NO Authentication failed.");
-	o_buffer_flush(client->outbuf);
+	o_stream_flush(client->output);
 
 	/* get back to normal client input */
 	if (client->io != NULL)
@@ -110,11 +110,11 @@
 	t_push();
 
 	base64_data = base64_encode(data, size);
-	o_buffer_send(client->outbuf, "+ ", 2);
-	o_buffer_send(client->outbuf, base64_data, strlen(base64_data));
-	o_buffer_send(client->outbuf, "\r\n", 2);
+	o_stream_send(client->output, "+ ", 2);
+	o_stream_send(client->output, base64_data, strlen(base64_data));
+	o_stream_send(client->output, "\r\n", 2);
 
-	o_buffer_flush(client->outbuf);
+	o_stream_flush(client->output);
 
 	t_pop();
 }
@@ -244,7 +244,7 @@
 	if (!client_read(client))
 		return;
 
-	line = i_buffer_next_line(client->inbuf);
+	line = i_stream_next_line(client->input);
 	if (line == NULL)
 		return;
 
--- a/src/login/client.c	Fri Dec 06 00:37:33 2002 +0200
+++ b/src/login/client.c	Fri Dec 06 03:09:22 2002 +0200
@@ -3,8 +3,8 @@
 #include "common.h"
 #include "hash.h"
 #include "ioloop.h"
-#include "ibuffer.h"
-#include "obuffer.h"
+#include "istream.h"
+#include "ostream.h"
 #include "process-title.h"
 #include "client.h"
 #include "client-authenticate.h"
@@ -66,7 +66,7 @@
 	}
 
 	client_send_tagline(client, "OK Begin TLS negotiation now.");
-	o_buffer_flush(client->outbuf);
+	o_stream_flush(client->output);
 
 	/* must be removed before ssl_proxy_new(), since it may
 	   io_add() the same fd. */
@@ -82,12 +82,12 @@
 
 		client->fd = fd_ssl;
 
-		i_buffer_unref(client->inbuf);
-		o_buffer_unref(client->outbuf);
+		i_stream_unref(client->input);
+		o_stream_unref(client->output);
 
-		client->inbuf = i_buffer_create_file(fd_ssl, default_pool,
+		client->input = i_stream_create_file(fd_ssl, default_pool,
 						     8192, FALSE);
-		client->outbuf = o_buffer_create_file(fd_ssl, default_pool,
+		client->output = o_stream_create_file(fd_ssl, default_pool,
 						      1024, IO_PRIORITY_DEFAULT,
 						      FALSE);
 	} else {
@@ -115,7 +115,7 @@
 
 int client_read(Client *client)
 {
-	switch (i_buffer_read(client->inbuf)) {
+	switch (i_stream_read(client->input)) {
 	case -2:
 		/* buffer full */
 		client_send_line(client, "* BYE Input buffer full, aborting");
@@ -211,9 +211,9 @@
 		return;
 
 	client_ref(client);
-	o_buffer_cork(client->outbuf);
+	o_stream_cork(client->output);
 
-	while ((line = i_buffer_next_line(client->inbuf)) != NULL) {
+	while ((line = i_stream_next_line(client->input)) != NULL) {
 		/* split the arguments, make sure we have at
 		   least tag + command */
 		i_free(client->tag);
@@ -228,7 +228,7 @@
 	}
 
 	if (client_unref(client))
-		o_buffer_flush(client->outbuf);
+		o_stream_flush(client->output);
 }
 
 static void client_hash_destroy_oldest(void *key, void *value __attr_unused__,
@@ -286,8 +286,8 @@
 	memcpy(&client->ip, ip, sizeof(IPADDR));
 	client->fd = fd;
 	client->io = io_add(fd, IO_READ, client_input, client);
-	client->inbuf = i_buffer_create_file(fd, default_pool, 8192, FALSE);
-	client->outbuf = o_buffer_create_file(fd, default_pool, 1024,
+	client->input = i_stream_create_file(fd, default_pool, 8192, FALSE);
+	client->output = o_stream_create_file(fd, default_pool, 1024,
 					      IO_PRIORITY_DEFAULT, FALSE);
         client->last_input = ioloop_time;
 	hash_insert(clients, client, client);
@@ -306,8 +306,8 @@
 
 	hash_remove(clients, client);
 
-	i_buffer_close(client->inbuf);
-	o_buffer_close(client->outbuf);
+	i_stream_close(client->input);
+	o_stream_close(client->output);
 
 	if (client->io != NULL) {
 		io_remove(client->io);
@@ -330,8 +330,8 @@
 	if (--client->refcount > 0)
 		return TRUE;
 
-	i_buffer_unref(client->inbuf);
-	o_buffer_unref(client->outbuf);
+	i_stream_unref(client->input);
+	o_stream_unref(client->output);
 
 	i_free(client->tag);
 	i_free(client->plain_login);
@@ -343,8 +343,8 @@
 
 void client_send_line(Client *client, const char *line)
 {
-	o_buffer_send(client->outbuf, line, strlen(line));
-	o_buffer_send(client->outbuf, "\r\n", 2);
+	o_stream_send(client->output, line, strlen(line));
+	o_stream_send(client->output, "\r\n", 2);
 }
 
 void client_send_tagline(Client *client, const char *line)
--- a/src/login/client.h	Fri Dec 06 00:37:33 2002 +0200
+++ b/src/login/client.h	Fri Dec 06 03:09:22 2002 +0200
@@ -10,8 +10,8 @@
 
 	int fd;
 	IO io;
-	IBuffer *inbuf;
-	OBuffer *outbuf;
+	IStream *input;
+	OStream *output;
 
 	time_t last_input;
 	char *tag;
--- a/src/master/auth-process.c	Fri Dec 06 00:37:33 2002 +0200
+++ b/src/master/auth-process.c	Fri Dec 06 03:09:22 2002 +0200
@@ -5,7 +5,7 @@
 #include "env-util.h"
 #include "fd-close-on-exec.h"
 #include "network.h"
-#include "obuffer.h"
+#include "ostream.h"
 #include "restrict-access.h"
 #include "restrict-process-size.h"
 #include "auth-process.h"
@@ -24,7 +24,7 @@
 	pid_t pid;
 	int fd;
 	IO io;
-	OBuffer *outbuf;
+	OStream *output;
 
 	unsigned int reply_pos;
 	char reply_buf[sizeof(AuthCookieReplyData)];
@@ -127,7 +127,7 @@
 	p->pid = pid;
 	p->fd = fd;
 	p->io = io_add(fd, IO_READ, auth_process_input, p);
-	p->outbuf = o_buffer_create_file(fd, default_pool,
+	p->output = o_stream_create_file(fd, default_pool,
 					 sizeof(AuthCookieRequestData)*100,
 					 IO_PRIORITY_DEFAULT, FALSE);
 
@@ -159,7 +159,7 @@
 
 	(void)unlink(t_strconcat(set_login_dir, "/", p->name, NULL));
 
-	o_buffer_unref(p->outbuf);
+	o_stream_unref(p->output);
 	io_remove(p->io);
 	(void)close(p->fd);
 	i_free(p->name);
@@ -285,7 +285,7 @@
 	req.id = id;
 	memcpy(req.cookie, cookie, AUTH_COOKIE_SIZE);
 
-	if (o_buffer_send(process->outbuf, &req, sizeof(req)) < 0)
+	if (o_stream_send(process->output, &req, sizeof(req)) < 0)
 		auth_process_destroy(process);
 
 	push_request(process, id, callback, context);
--- a/src/master/login-process.c	Fri Dec 06 00:37:33 2002 +0200
+++ b/src/master/login-process.c	Fri Dec 06 03:09:22 2002 +0200
@@ -3,7 +3,7 @@
 #include "common.h"
 #include "ioloop.h"
 #include "network.h"
-#include "obuffer.h"
+#include "ostream.h"
 #include "fdpass.h"
 #include "fd-close-on-exec.h"
 #include "env-util.h"
@@ -25,7 +25,7 @@
 	pid_t pid;
 	int fd;
 	IO io;
-	OBuffer *outbuf;
+	OStream *output;
 	unsigned int listening:1;
 	unsigned int destroyed:1;
 };
@@ -81,7 +81,7 @@
 	reply.id = request->login_id;
 
 	process = request->process;
-	if (o_buffer_send(process->outbuf, &reply, sizeof(reply)) < 0)
+	if (o_stream_send(process->output, &reply, sizeof(reply)) < 0)
 		login_process_destroy(process);
 
 	(void)close(request->fd);
@@ -182,7 +182,7 @@
 	p->fd = fd;
 	p->listening = TRUE;
 	p->io = io_add(fd, IO_READ, login_process_input, p);
-	p->outbuf = o_buffer_create_file(fd, default_pool,
+	p->output = o_stream_create_file(fd, default_pool,
 					 sizeof(MasterReply)*10,
 					 IO_PRIORITY_DEFAULT, FALSE);
 
@@ -215,7 +215,7 @@
 	if (p->listening)
 		listening_processes--;
 
-	o_buffer_close(p->outbuf);
+	o_stream_close(p->output);
 	io_remove(p->io);
 	(void)close(p->fd);
 
@@ -232,7 +232,7 @@
 	if (--p->refcount > 0)
 		return;
 
-	o_buffer_unref(p->outbuf);
+	o_stream_unref(p->output);
 	i_free(p);
 }
 
--- a/src/master/settings.c	Fri Dec 06 00:37:33 2002 +0200
+++ b/src/master/settings.c	Fri Dec 06 03:09:22 2002 +0200
@@ -1,7 +1,7 @@
 /* Copyright (C) 2002 Timo Sirainen */
 
 #include "lib.h"
-#include "ibuffer.h"
+#include "istream.h"
 #include "settings.h"
 
 #include <stdio.h>
@@ -433,7 +433,7 @@
 
 void settings_read(const char *path)
 {
-	IBuffer *inbuf;
+	IStream *input;
 	const char *errormsg;
 	char *line, *key, *p;
 	int fd, linenum;
@@ -445,11 +445,11 @@
 		i_fatal("Can't open configuration file %s: %m", path);
 
 	linenum = 0;
-	inbuf = i_buffer_create_file(fd, default_pool, 2048, TRUE);
+	input = i_stream_create_file(fd, default_pool, 2048, TRUE);
 	for (;;) {
-		line = i_buffer_next_line(inbuf);
+		line = i_stream_next_line(input);
 		if (line == NULL) {
-			if (i_buffer_read(inbuf) <= 0)
+			if (i_stream_read(input) <= 0)
 				break;
                         continue;
 		}
@@ -494,7 +494,7 @@
 		}
 	};
 
-	i_buffer_unref(inbuf);
+	i_stream_unref(input);
 
         settings_verify();
 }