Mercurial > dovecot > original-hg > dovecot-1.2
changeset 410:1f0e7229ee58 HEAD
Split IOBuffer into mmaped IBuffer, file IBuffer, memory data IBuffer and
file OBuffer.
line wrap: on
line diff
--- a/src/auth/login-connection.c Sun Oct 13 18:52:19 2002 +0300 +++ b/src/auth/login-connection.c Mon Oct 14 02:49:11 2002 +0300 @@ -2,7 +2,8 @@ #include "common.h" #include "network.h" -#include "iobuffer.h" +#include "ibuffer.h" +#include "obuffer.h" #include "login-connection.h" #include <stdlib.h> @@ -18,7 +19,8 @@ int fd; IO io; - IOBuffer *inbuf, *outbuf; + IBuffer *inbuf; + OBuffer *outbuf; AuthRequestType type; }; @@ -32,10 +34,10 @@ i_assert(reply->data_size <= AUTH_MAX_REPLY_DATA_SIZE); - if (io_buffer_send(conn->outbuf, reply, sizeof(AuthReplyData)) < 0) + if (o_buffer_send(conn->outbuf, reply, sizeof(AuthReplyData)) < 0) login_connection_destroy(conn); else if (reply->data_size > 0) { - if (io_buffer_send(conn->outbuf, data, reply->data_size) < 0) + if (o_buffer_send(conn->outbuf, data, reply->data_size) < 0) login_connection_destroy(conn); } } @@ -44,10 +46,10 @@ IO io __attr_unused__) { LoginConnection *conn = context; - unsigned char *data; + const unsigned char *data; size_t size; - switch (io_buffer_read(conn->inbuf)) { + switch (i_buffer_read(conn->inbuf)) { case 0: return; case -1: @@ -62,7 +64,7 @@ return; } - data = io_buffer_get_data(conn->inbuf, &size); + data = i_buffer_get_data(conn->inbuf, &size); if (size < sizeof(AuthRequestType)) return; @@ -80,7 +82,7 @@ return; memcpy(&request, data, sizeof(request)); - io_buffer_skip(conn->inbuf, sizeof(request)); + i_buffer_skip(conn->inbuf, sizeof(request)); /* we have a full init request */ auth_init_request(&request, request_callback, conn); @@ -95,8 +97,7 @@ if (size < sizeof(request) + request.data_size) return; - io_buffer_skip(conn->inbuf, - sizeof(request) + request.data_size); + i_buffer_skip(conn->inbuf, sizeof(request) + request.data_size); /* we have a full continued request */ auth_continue_request(&request, data + sizeof(request), @@ -117,18 +118,18 @@ conn = i_new(LoginConnection, 1); conn->fd = fd; - conn->inbuf = io_buffer_create(fd, default_pool, - IO_PRIORITY_DEFAULT, MAX_INBUF_SIZE); - conn->outbuf = io_buffer_create(fd, default_pool, - IO_PRIORITY_DEFAULT, MAX_OUTBUF_SIZE); + conn->inbuf = i_buffer_create_file(fd, default_pool, MAX_INBUF_SIZE, + FALSE); + conn->outbuf = o_buffer_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; conn->next = connections; connections = conn; - if (io_buffer_send(conn->outbuf, &auth_init_data, - sizeof(auth_init_data)) < 0) { + if (o_buffer_send(conn->outbuf, &auth_init_data, + sizeof(auth_init_data)) < 0) { login_connection_destroy(conn); conn = NULL; } @@ -147,8 +148,8 @@ } } - io_buffer_close(conn->inbuf); - io_buffer_close(conn->outbuf); + i_buffer_unref(conn->inbuf); + o_buffer_unref(conn->outbuf); io_remove(conn->io); net_disconnect(conn->fd);
--- a/src/auth/master.c Sun Oct 13 18:52:19 2002 +0300 +++ b/src/auth/master.c Mon Oct 14 02:49:11 2002 +0300 @@ -1,7 +1,7 @@ /* Copyright (C) 2002 Timo Sirainen */ #include "common.h" -#include "iobuffer.h" +#include "obuffer.h" #include "network.h" #include "cookie.h" @@ -9,7 +9,7 @@ static AuthCookieReplyData failure_reply; -static IOBuffer *outbuf; +static OBuffer *outbuf; static IO io_master; static unsigned int master_pos; @@ -33,7 +33,7 @@ } reply->id = request->id; - switch (io_buffer_send(outbuf, reply, sizeof(AuthCookieReplyData))) { + switch (o_buffer_send(outbuf, reply, sizeof(AuthCookieReplyData))) { case -2: i_fatal("Master transmit buffer full, aborting"); case -1: @@ -70,13 +70,14 @@ memset(&failure_reply, 0, sizeof(failure_reply)); master_pos = 0; - outbuf = io_buffer_create(MASTER_SOCKET_FD, default_pool, - IO_PRIORITY_DEFAULT, MAX_OUTBUF_SIZE); + outbuf = o_buffer_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); } void master_deinit(void) { - io_buffer_unref(outbuf); + o_buffer_unref(outbuf); io_remove(io_master); }
--- a/src/auth/userinfo-passwd-file.c Sun Oct 13 18:52:19 2002 +0300 +++ b/src/auth/userinfo-passwd-file.c Mon Oct 14 02:49:11 2002 +0300 @@ -10,7 +10,7 @@ #ifdef USERINFO_PASSWD_FILE -#include "iobuffer.h" +#include "ibuffer.h" #include "hash.h" #include "hex-binary.h" #include "md5.h" @@ -294,15 +294,15 @@ static void passwd_file_parse_file(PasswdFile *pw) { - IOBuffer *inbuf; + IBuffer *inbuf; char *const *args; char *line; - inbuf = io_buffer_create_file(pw->fd, default_pool, 2048, FALSE); + inbuf = i_buffer_create_file(pw->fd, default_pool, 2048, FALSE); for (;;) { - line = io_buffer_next_line(inbuf); + line = i_buffer_next_line(inbuf); if (line == NULL) { - if (io_buffer_read(inbuf) <= 0) + if (i_buffer_read(inbuf) <= 0) break; continue; } @@ -318,7 +318,7 @@ } t_pop(); } - io_buffer_unref(inbuf); + i_buffer_unref(inbuf); } static PasswdFile *passwd_file_parse(const char *path)
--- a/src/imap/client.c Sun Oct 13 18:52:19 2002 +0300 +++ b/src/imap/client.c Mon Oct 14 02:49:11 2002 +0300 @@ -2,7 +2,8 @@ #include "common.h" #include "network.h" -#include "iobuffer.h" +#include "ibuffer.h" +#include "obuffer.h" #include "commands.h" #include <stdlib.h> @@ -33,8 +34,8 @@ { Client *client = context; - io_buffer_close(client->inbuf); - io_buffer_close(client->outbuf); + i_buffer_close(client->inbuf); + o_buffer_close(client->outbuf); } static void client_input_timeout(void *context, @@ -44,37 +45,35 @@ client_send_line(my_client, "* BYE Disconnected for inactivity " "while waiting for command data."); - io_buffer_close(client->outbuf); + o_buffer_close(client->outbuf); } -Client *client_create(int hin, int hout, int socket, MailStorage *storage) +Client *client_create(int hin, int hout, MailStorage *storage) { Client *client; client = i_new(Client, 1); - client->socket = socket; - client->inbuf = io_buffer_create(hin, default_pool, 0, - MAX_INBUF_SIZE); - client->outbuf = io_buffer_create(hout, default_pool, 0, 0); + client->inbuf = i_buffer_create_file(hin, default_pool, + MAX_INBUF_SIZE, FALSE); + client->outbuf = o_buffer_create_file(hout, default_pool, 4096, + IO_PRIORITY_DEFAULT, FALSE); /* always use nonblocking I/O */ net_set_nonblock(hin, TRUE); net_set_nonblock(hout, TRUE); - /* set timeout for sending data */ - io_buffer_set_blocking(client->outbuf, 4096, CLIENT_OUTPUT_TIMEOUT, - client_output_timeout, client); - /* set timeout for reading expected data (eg. APPEND). This is different from the actual idle time. */ - io_buffer_set_blocking(client->inbuf, 0, CLIENT_CMDINPUT_TIMEOUT, - client_input_timeout, client); + i_buffer_set_blocking(client->inbuf, CLIENT_CMDINPUT_TIMEOUT, + client_input_timeout, client); - client->inbuf->file = !socket; - client->outbuf->file = !socket; + /* set timeout for sending data */ + o_buffer_set_blocking(client->outbuf, CLIENT_OUTPUT_TIMEOUT, + client_output_timeout, client); - client->io = io_add(socket, IO_READ, (IOFunc) client_input, client); - client->parser = imap_parser_create(client->inbuf, client->outbuf); + client->io = io_add(hin, IO_READ, (IOFunc) client_input, client); + client->parser = imap_parser_create(client->inbuf, client->outbuf, + MAX_INBUF_SIZE); client->last_input = ioloop_time; client->storage = storage; @@ -86,7 +85,7 @@ void client_destroy(Client *client) { - io_buffer_send_flush(client->outbuf); + o_buffer_flush(client->outbuf); if (client->mailbox != NULL) client->mailbox->close(client->mailbox); @@ -95,8 +94,8 @@ imap_parser_destroy(client->parser); io_remove(client->io); - io_buffer_unref(client->inbuf); - io_buffer_unref(client->outbuf); + i_buffer_unref(client->inbuf); + o_buffer_unref(client->outbuf); i_free(client); @@ -107,43 +106,24 @@ void client_disconnect(Client *client) { - io_buffer_send_flush(client->outbuf); + o_buffer_flush(client->outbuf); - io_buffer_close(client->inbuf); - io_buffer_close(client->outbuf); + i_buffer_close(client->inbuf); + o_buffer_close(client->outbuf); } void client_send_line(Client *client, const char *data) { - unsigned char *buf; - size_t len; - if (client->outbuf->closed) return; - len = strlen(data); - - buf = io_buffer_get_space(client->outbuf, len+2); - if (buf != NULL) { - memcpy(buf, data, len); - buf[len++] = '\r'; buf[len++] = '\n'; - - /* Returns error only if we disconnected - - we don't need to do anything about it. */ - (void)io_buffer_send_buffer(client->outbuf, len); - } else { - /* not enough space in output buffer, send this directly. - will block. */ - io_buffer_send(client->outbuf, data, len); - io_buffer_send(client->outbuf, "\r\n", 2); - } + (void)o_buffer_send(client->outbuf, data, strlen(data)); + (void)o_buffer_send(client->outbuf, "\r\n", 2); } void client_send_tagline(Client *client, const char *data) { const char *tag = client->cmd_tag; - unsigned char *buf; - size_t taglen, len; if (client->outbuf->closed) return; @@ -151,24 +131,10 @@ if (tag == NULL || *tag == '\0') tag = "*"; - taglen = strlen(tag); - len = strlen(data); - - buf = io_buffer_get_space(client->outbuf, taglen+1+len+2); - if (buf != NULL) { - memcpy(buf, tag, taglen); buf[taglen] = ' '; - buf += taglen+1; - - memcpy(buf, data, len); buf += len; - buf[0] = '\r'; buf[1] = '\n'; - - (void)io_buffer_send_buffer(client->outbuf, taglen+1+len+2); - } else { - const char *str; - - str = t_strconcat(tag, " ", data, "\r\n", NULL); - (void)io_buffer_send(client->outbuf, str, strlen(str)); - } + (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 client_send_command_error(Client *client, const char *msg) @@ -260,16 +226,16 @@ returns TRUE if newline was found. */ static int client_skip_line(Client *client) { - unsigned char *data; + const unsigned char *data; size_t i, data_size; /* get the beginning of data in input buffer */ - data = io_buffer_get_data(client->inbuf, &data_size); + data = i_buffer_get_data(client->inbuf, &data_size); for (i = 0; i < data_size; i++) { if (data[i] == '\n') { client->inbuf_skip_line = FALSE; - io_buffer_skip(client->inbuf, i+1); + i_buffer_skip(client->inbuf, i+1); break; } } @@ -338,7 +304,7 @@ { client->last_input = ioloop_time; - switch (io_buffer_read(client->inbuf)) { + switch (i_buffer_read(client->inbuf)) { case -1: /* disconnected */ client_destroy(client); @@ -354,10 +320,10 @@ break; } - io_buffer_cork(client->outbuf); + o_buffer_cork(client->outbuf); while (client_handle_input(client)) ; - io_buffer_send_flush(client->outbuf); + o_buffer_flush(client->outbuf); if (client->outbuf->closed) client_destroy(client);
--- a/src/imap/client.h Sun Oct 13 18:52:19 2002 +0300 +++ b/src/imap/client.h Mon Oct 14 02:49:11 2002 +0300 @@ -11,7 +11,8 @@ struct _Client { int socket; IO io; - IOBuffer *inbuf, *outbuf; + IBuffer *inbuf; + OBuffer *outbuf; MailStorage *storage; Mailbox *mailbox; @@ -32,7 +33,7 @@ /* Create new client with specified input/output handles. socket specifies if the handle is a socket. */ -Client *client_create(int hin, int hout, int socket, MailStorage *storage); +Client *client_create(int hin, int hout, MailStorage *storage); void client_destroy(Client *client); /* Disconnect client connection */
--- a/src/imap/cmd-append.c Sun Oct 13 18:52:19 2002 +0300 +++ b/src/imap/cmd-append.c Mon Oct 14 02:49:11 2002 +0300 @@ -2,7 +2,7 @@ #include "common.h" #include "ioloop.h" -#include "iobuffer.h" +#include "obuffer.h" #include "commands.h" #include "imap-parser.h" #include "imap-date.h" @@ -120,8 +120,8 @@ } } - io_buffer_send(client->outbuf, "+ OK\r\n", 6); - io_buffer_send_flush(client->outbuf); + o_buffer_send(client->outbuf, "+ OK\r\n", 6); + o_buffer_flush(client->outbuf); /* save the mail */ failed = !box->save(box, flags, custom_flags, internal_date,
--- a/src/imap/main.c Sun Oct 13 18:52:19 2002 +0300 +++ b/src/imap/main.c Mon Oct 14 02:49:11 2002 +0300 @@ -70,7 +70,7 @@ "autodetection failed (home %s)", home); } } else { - client = client_create(0, 1, FALSE, storage); + client = client_create(0, 1, storage); tag = getenv("LOGIN_TAG"); if (tag == NULL || *tag == '\0')
--- a/src/lib-imap/imap-bodystructure.c Sun Oct 13 18:52:19 2002 +0300 +++ b/src/lib-imap/imap-bodystructure.c Mon Oct 14 02:49:11 2002 +0300 @@ -1,7 +1,7 @@ /* Copyright (C) 2002 Timo Sirainen */ #include "lib.h" -#include "iobuffer.h" +#include "ibuffer.h" #include "temp-string.h" #include "rfc822-tokenize.h" #include "message-parser.h" @@ -213,15 +213,15 @@ t_pop(); } -static void part_parse_headers(MessagePart *part, IOBuffer *inbuf, +static void part_parse_headers(MessagePart *part, IBuffer *inbuf, 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->offset - start_offset); - io_buffer_skip(inbuf, part->physical_pos - - (inbuf->offset - start_offset)); + i_assert(part->physical_pos >= inbuf->v_offset - start_offset); + i_buffer_skip(inbuf, part->physical_pos - + (inbuf->v_offset - start_offset)); message_parse_header(part, inbuf, NULL, parse_header, pool); @@ -239,6 +239,8 @@ { MessagePartBodyData *data = part->context; + i_assert(data != NULL); + if (part->children != NULL) part_write_bodystructure(part->children, str, extended); else { @@ -405,14 +407,14 @@ } const char *imap_part_get_bodystructure(Pool pool, MessagePart **part, - IOBuffer *inbuf, int extended) + IBuffer *inbuf, int extended) { uoff_t start_offset; if (*part == NULL) *part = message_parse(pool, inbuf, parse_header, pool); else { - start_offset = inbuf->offset; + start_offset = inbuf->v_offset; part_parse_headers(*part, inbuf, start_offset, pool); }
--- a/src/lib-imap/imap-bodystructure.h Sun Oct 13 18:52:19 2002 +0300 +++ b/src/lib-imap/imap-bodystructure.h Mon Oct 14 02:49:11 2002 +0300 @@ -4,6 +4,6 @@ /* 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, - IOBuffer *inbuf, int extended); + IBuffer *inbuf, int extended); #endif
--- a/src/lib-imap/imap-envelope.c Sun Oct 13 18:52:19 2002 +0300 +++ b/src/lib-imap/imap-envelope.c Mon Oct 14 02:49:11 2002 +0300 @@ -1,7 +1,7 @@ /* Copyright (C) 2002 Timo Sirainen */ #include "lib.h" -#include "iobuffer.h" +#include "ibuffer.h" #include "temp-string.h" #include "rfc822-address.h" #include "imap-parser.h" @@ -231,17 +231,18 @@ const char *imap_envelope_parse(const char *envelope, ImapEnvelopeField field) { - IOBuffer *inbuf; + IBuffer *inbuf; ImapParser *parser; ImapArg *args; const char *value; + size_t len; int ret; i_assert(field < IMAP_ENVELOPE_FIELDS); - inbuf = io_buffer_create_from_data(envelope, strlen(envelope), - data_stack_pool); - parser = imap_parser_create(inbuf, NULL); + len = strlen(envelope); + inbuf = i_buffer_create_from_data(data_stack_pool, envelope, len); + parser = imap_parser_create(inbuf, NULL, len); ret = imap_parser_read_args(parser, field, 0, &args); if (ret < 0) @@ -251,6 +252,6 @@ imap_envelope_parse_arg(&args[field], field, envelope); imap_parser_destroy(parser); - io_buffer_unref(inbuf); + i_buffer_unref(inbuf); return value; }
--- a/src/lib-imap/imap-message-cache.c Sun Oct 13 18:52:19 2002 +0300 +++ b/src/lib-imap/imap-message-cache.c Mon Oct 14 02:49:11 2002 +0300 @@ -1,7 +1,7 @@ /* Copyright (C) 2002 Timo Sirainen */ #include "lib.h" -#include "iobuffer.h" +#include "ibuffer.h" #include "temp-string.h" #include "mmap-util.h" #include "message-parser.h" @@ -47,7 +47,7 @@ int messages_count; CachedMessage *open_msg; - IOBuffer *open_inbuf; + IBuffer *open_inbuf; void *context; }; @@ -160,7 +160,7 @@ { if (cache->open_inbuf == NULL) cache->open_inbuf = cache->iface->open_mail(cache->context); - else if (offset < cache->open_inbuf->offset) { + else if (offset < cache->open_inbuf->v_offset) { /* need to rewind */ cache->open_inbuf = cache->iface->inbuf_rewind(cache->open_inbuf, @@ -170,9 +170,9 @@ if (cache->open_inbuf == NULL) return FALSE; - i_assert(offset >= cache->open_inbuf->offset); + i_assert(offset >= cache->open_inbuf->v_offset); - io_buffer_skip(cache->open_inbuf, offset - cache->open_inbuf->offset); + i_buffer_skip(cache->open_inbuf, offset - cache->open_inbuf->v_offset); return TRUE; } @@ -342,7 +342,7 @@ void imap_msgcache_close(ImapMessageCache *cache) { if (cache->open_inbuf != NULL) { - io_buffer_unref(cache->open_inbuf); + i_buffer_unref(cache->open_inbuf); cache->open_inbuf = NULL; } @@ -386,7 +386,7 @@ return cache->open_msg->part; } -int imap_msgcache_get_rfc822(ImapMessageCache *cache, IOBuffer **inbuf, +int imap_msgcache_get_rfc822(ImapMessageCache *cache, IBuffer **inbuf, MessageSize *hdr_size, MessageSize *body_size) { CachedMessage *msg; @@ -422,11 +422,11 @@ return TRUE; } -static void get_partial_size(IOBuffer *inbuf, +static void get_partial_size(IBuffer *inbuf, uoff_t virtual_skip, uoff_t max_virtual_size, MessageSize *partial, MessageSize *dest) { - unsigned char *msg; + const unsigned char *msg; size_t size; int cr_skipped; @@ -434,7 +434,7 @@ if (partial->virtual_size > virtual_skip) memset(partial, 0, sizeof(MessageSize)); else { - io_buffer_skip(inbuf, partial->physical_size); + i_buffer_skip(inbuf, partial->physical_size); virtual_skip -= partial->virtual_size; } @@ -442,7 +442,7 @@ if (!cr_skipped) { /* see if we need to add virtual CR */ - if (io_buffer_read_data_blocking(inbuf, &msg, &size, 0) > 0) { + if (i_buffer_read_data(inbuf, &msg, &size, 0) > 0) { if (msg[0] == '\n') dest->virtual_size++; } @@ -455,7 +455,7 @@ uoff_t virtual_skip, uoff_t max_virtual_size, int get_header, MessageSize *size, - IOBuffer **inbuf) + IBuffer **inbuf) { CachedMessage *msg; uoff_t physical_skip; @@ -513,7 +513,7 @@ return TRUE; } -int imap_msgcache_get_data(ImapMessageCache *cache, IOBuffer **inbuf) +int imap_msgcache_get_data(ImapMessageCache *cache, IBuffer **inbuf) { i_assert(cache->open_msg != NULL);
--- a/src/lib-imap/imap-message-cache.h Sun Oct 13 18:52:19 2002 +0300 +++ b/src/lib-imap/imap-message-cache.h Mon Oct 14 02:49:11 2002 +0300 @@ -24,10 +24,10 @@ typedef struct { /* Open mail for reading. */ - IOBuffer *(*open_mail)(void *context); + IBuffer *(*open_mail)(void *context); /* Rewind input buffer to beginning, possibly closing the old buffer if it can't directly be rewinded. */ - IOBuffer *(*inbuf_rewind)(IOBuffer *inbuf, void *context); + IBuffer *(*inbuf_rewind)(IBuffer *inbuf, void *context); /* Returns field if it's already cached, or NULL. */ const char *(*get_cached_field)(ImapCacheField field, void *context); @@ -59,7 +59,7 @@ /* Returns TRUE if successful. If inbuf 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, IOBuffer **inbuf, +int imap_msgcache_get_rfc822(ImapMessageCache *cache, IBuffer **inbuf, MessageSize *hdr_size, MessageSize *body_size); /* Returns TRUE if successful. *inbuf is set to point to the first non-skipped @@ -68,10 +68,10 @@ uoff_t virtual_skip, uoff_t max_virtual_size, int get_header, MessageSize *size, - IOBuffer **inbuf); + IBuffer **inbuf); /* Returns TRUE if successful. *inbuf is set to point to beginning of message. */ -int imap_msgcache_get_data(ImapMessageCache *cache, IOBuffer **inbuf); +int imap_msgcache_get_data(ImapMessageCache *cache, IBuffer **inbuf); #endif
--- a/src/lib-imap/imap-parser.c Sun Oct 13 18:52:19 2002 +0300 +++ b/src/lib-imap/imap-parser.c Mon Oct 14 02:49:11 2002 +0300 @@ -1,7 +1,8 @@ /* Copyright (C) 2002 Timo Sirainen */ #include "lib.h" -#include "iobuffer.h" +#include "ibuffer.h" +#include "obuffer.h" #include "imap-parser.h" #define is_linebreak(c) \ @@ -17,7 +18,9 @@ struct _ImapParser { Pool pool; - IOBuffer *inbuf, *outbuf; + IBuffer *inbuf; + OBuffer *outbuf; + size_t max_literal_size; unsigned int pos; ImapArg *args; @@ -39,14 +42,16 @@ unsigned int error:1; }; -ImapParser *imap_parser_create(IOBuffer *inbuf, IOBuffer *outbuf) +ImapParser *imap_parser_create(IBuffer *inbuf, OBuffer *outbuf, + size_t max_literal_size) { ImapParser *parser; parser = i_new(ImapParser, 1); - parser->pool = pool_create("IMAP parser", 8192, FALSE); + parser->pool = pool_create("IMAP parser", 8192, FALSE); parser->inbuf = inbuf; parser->outbuf = outbuf; + parser->max_literal_size = max_literal_size; return parser; } @@ -84,7 +89,7 @@ break; } - io_buffer_skip(parser->inbuf, i); + i_buffer_skip(parser->inbuf, i); parser->cur_pos = 0; *data += i; @@ -279,15 +284,15 @@ static int imap_parser_literal_end(ImapParser *parser) { if ((parser->flags & IMAP_PARSE_FLAG_LITERAL_SIZE) == 0) { - if (parser->literal_size > parser->inbuf->max_buffer_size) { + if (parser->literal_size > parser->max_literal_size) { /* too long string, abort. */ parser->error = TRUE; return FALSE; } if (parser->outbuf != NULL) { - io_buffer_send(parser->outbuf, "+ OK\r\n", 6); - io_buffer_send_flush(parser->outbuf); + o_buffer_send(parser->outbuf, "+ OK\r\n", 6); + o_buffer_flush(parser->outbuf); } } @@ -306,7 +311,7 @@ /* expecting digits + "}" */ for (i = parser->cur_pos; i < data_size; i++) { if (data[i] == '}') { - io_buffer_skip(parser->inbuf, i+1); + i_buffer_skip(parser->inbuf, i+1); if (!imap_parser_literal_end(parser)) return FALSE; break; @@ -338,14 +343,14 @@ return TRUE; data++; data_size--; - io_buffer_skip(parser->inbuf, 1); + i_buffer_skip(parser->inbuf, 1); } if (*data != '\n') return FALSE; data++; data_size--; - io_buffer_skip(parser->inbuf, 1); + i_buffer_skip(parser->inbuf, 1); parser->literal_skip_crlf = FALSE; i_assert(parser->cur_pos == 0); @@ -373,7 +378,7 @@ char *data; size_t data_size; - data = (char *) io_buffer_get_data(parser->inbuf, &data_size); + data = (char *) i_buffer_get_data(parser->inbuf, &data_size); if (data_size == 0) return FALSE; @@ -441,7 +446,7 @@ /* pass through to parsing data. since inbuf->skip was modified, we need to get the data start position again. */ - data = (char *) io_buffer_get_data(parser->inbuf, &data_size); + data = (char *) i_buffer_get_data(parser->inbuf, &data_size); case ARG_PARSE_LITERAL_DATA: imap_parser_read_literal_data(parser, data, data_size); break; @@ -502,7 +507,7 @@ size_t i, data_size; /* get the beginning of data in input buffer */ - data = (char *) io_buffer_get_data(parser->inbuf, &data_size); + data = (char *) i_buffer_get_data(parser->inbuf, &data_size); for (i = 0; i < data_size; i++) { if (data[i] == ' ' || data[i] == '\r' || data[i] == '\n') @@ -510,7 +515,7 @@ } if (i < data_size) { - io_buffer_skip(parser->inbuf, i + (data[i] == ' ' ? 1 : 0)); + i_buffer_skip(parser->inbuf, i + (data[i] == ' ' ? 1 : 0)); return p_strndup(parser->pool, data, i); } else { return NULL; @@ -523,7 +528,7 @@ size_t i, data_size; /* get the beginning of data in input buffer */ - data = (char *) io_buffer_get_data(parser->inbuf, &data_size); + data = (char *) i_buffer_get_data(parser->inbuf, &data_size); for (i = 0; i < data_size; i++) { if (data[i] == '\r' || data[i] == '\n') @@ -531,7 +536,7 @@ } if (i < data_size) { - io_buffer_skip(parser->inbuf, i); + i_buffer_skip(parser->inbuf, i); return p_strndup(parser->pool, data, i); } else { return NULL;
--- a/src/lib-imap/imap-parser.h Sun Oct 13 18:52:19 2002 +0300 +++ b/src/lib-imap/imap-parser.h Mon Oct 14 02:49:11 2002 +0300 @@ -38,9 +38,11 @@ }; /* Create new IMAP argument parser. The max. size of inbuf limits the - maximum size of each argument. outbuf is used for sending command - continuation requests for string literals. */ -ImapParser *imap_parser_create(IOBuffer *inbuf, IOBuffer *outbuf); + 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, + size_t max_literal_size); void imap_parser_destroy(ImapParser *parser); /* Reset the parser to initial state. */
--- a/src/lib-index/mail-index-update-cache.c Sun Oct 13 18:52:19 2002 +0300 +++ b/src/lib-index/mail-index-update-cache.c Mon Oct 14 02:49:11 2002 +0300 @@ -1,7 +1,7 @@ /* Copyright (C) 2002 Timo Sirainen */ #include "lib.h" -#include "iobuffer.h" +#include "ibuffer.h" #include "mail-index.h" #include <unistd.h> @@ -10,7 +10,7 @@ MailField cache_fields) { MailIndexUpdate *update; - IOBuffer *inbuf; + IBuffer *inbuf; int failed; inbuf = index->open_mail(index, rec); @@ -23,7 +23,7 @@ mail_index_update_headers(update, inbuf, cache_fields, NULL, NULL); failed = !index->update_end(update); - io_buffer_unref(inbuf); + i_buffer_unref(inbuf); return !failed; }
--- a/src/lib-index/mail-index-update.c Sun Oct 13 18:52:19 2002 +0300 +++ b/src/lib-index/mail-index-update.c Mon Oct 14 02:49:11 2002 +0300 @@ -1,7 +1,7 @@ /* Copyright (C) 2002 Timo Sirainen */ #include "lib.h" -#include "iobuffer.h" +#include "ibuffer.h" #include "ioloop.h" #include "rfc822-date.h" #include "rfc822-tokenize.h" @@ -319,7 +319,7 @@ } } -void mail_index_update_headers(MailIndexUpdate *update, IOBuffer *inbuf, +void mail_index_update_headers(MailIndexUpdate *update, IBuffer *inbuf, MailField cache_fields, MessageHeaderFunc header_func, void *context) { @@ -361,7 +361,7 @@ } } - start_offset = inbuf->offset; + start_offset = inbuf->v_offset; if (part == NULL) { part = message_parse(pool, inbuf, @@ -369,7 +369,7 @@ } else { /* cached, construct the bodystructure using it. also we need to parse the header.. */ - io_buffer_seek(inbuf, start_offset); + i_buffer_seek(inbuf, start_offset); message_parse_header(NULL, inbuf, NULL, update_header_func, &ctx); } @@ -380,7 +380,7 @@ if (cache_fields & FIELD_TYPE_BODY) { t_push(); - io_buffer_seek(inbuf, start_offset); + i_buffer_seek(inbuf, start_offset); value = imap_part_get_bodystructure(pool, &part, inbuf, FALSE); update->index->update_field(update, FIELD_TYPE_BODY, @@ -390,7 +390,7 @@ if (cache_fields & FIELD_TYPE_BODYSTRUCTURE) { t_push(); - io_buffer_seek(inbuf, start_offset); + i_buffer_seek(inbuf, start_offset); value = imap_part_get_bodystructure(pool, &part, inbuf, TRUE); update->index->update_field(update, @@ -414,7 +414,7 @@ update_header_func, &ctx); update->rec->header_size = hdr_size.physical_size; - update->rec->body_size = inbuf->size - inbuf->offset; + update->rec->body_size = inbuf->v_size - inbuf->v_offset; } if (ctx.envelope != NULL) {
--- a/src/lib-index/mail-index-util.c Sun Oct 13 18:52:19 2002 +0300 +++ b/src/lib-index/mail-index-util.c Mon Oct 14 02:49:11 2002 +0300 @@ -1,7 +1,7 @@ /* Copyright (C) 2002 Timo Sirainen */ #include "lib.h" -#include "iobuffer.h" +#include "ibuffer.h" #include "hostpid.h" #include "message-size.h" #include "message-part-serialize.h" @@ -111,7 +111,7 @@ int fastscan, uoff_t *virtual_size) { MessageSize hdr_size, body_size; - IOBuffer *inbuf; + IBuffer *inbuf; const void *part_data; size_t size; @@ -155,6 +155,6 @@ message_get_body_size(inbuf, &body_size, (uoff_t)-1); *virtual_size = body_size.virtual_size; - io_buffer_unref(inbuf); + i_buffer_unref(inbuf); return TRUE; }
--- a/src/lib-index/mail-index.h Sun Oct 13 18:52:19 2002 +0300 +++ b/src/lib-index/mail-index.h Mon Oct 14 02:49:11 2002 +0300 @@ -229,9 +229,9 @@ const void *(*lookup_field_raw)(MailIndex *index, MailIndexRecord *rec, MailField field, size_t *size); - /* Open mail file and return it as mmap()ed IOBuffer, or + /* Open mail file and return it as mmap()ed IBuffer, or NULL if failed. */ - IOBuffer *(*open_mail)(MailIndex *index, MailIndexRecord *rec); + IBuffer *(*open_mail)(MailIndex *index, MailIndexRecord *rec); /* Expunge a mail from index. Tree and modifylog is also updated. The index must be exclusively locked before calling this function. @@ -391,7 +391,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, IOBuffer *inbuf, +void mail_index_update_headers(MailIndexUpdate *update, IBuffer *inbuf, MailField cache_fields, MessageHeaderFunc header_func, void *context); int mail_index_update_cache(MailIndex *index);
--- a/src/lib-index/maildir/maildir-index.h Sun Oct 13 18:52:19 2002 +0300 +++ b/src/lib-index/maildir/maildir-index.h Mon Oct 14 02:49:11 2002 +0300 @@ -20,7 +20,7 @@ int maildir_index_build_dir(MailIndex *index, const char *source_dir, const char *dest_dir); -IOBuffer *maildir_open_mail(MailIndex *index, MailIndexRecord *rec); +IBuffer *maildir_open_mail(MailIndex *index, MailIndexRecord *rec); int maildir_record_update(MailIndexUpdate *update, int fd, off_t file_size);
--- a/src/lib-index/maildir/maildir-open.c Sun Oct 13 18:52:19 2002 +0300 +++ b/src/lib-index/maildir/maildir-open.c Mon Oct 14 02:49:11 2002 +0300 @@ -1,7 +1,7 @@ /* Copyright (C) 2002 Timo Sirainen */ #include "lib.h" -#include "iobuffer.h" +#include "ibuffer.h" #include "maildir-index.h" #include "mail-index-data.h" #include "mail-index-util.h" @@ -9,7 +9,7 @@ #include <unistd.h> #include <fcntl.h> -IOBuffer *maildir_open_mail(MailIndex *index, MailIndexRecord *rec) +IBuffer *maildir_open_mail(MailIndex *index, MailIndexRecord *rec) { const char *fname, *path; int fd; @@ -34,6 +34,6 @@ return NULL; } - return io_buffer_create_mmap(fd, default_pool, MAIL_MMAP_BLOCK_SIZE, 0, - 0, IOBUFFER_FLAG_AUTOCLOSE); + return i_buffer_create_mmap(fd, default_pool, MAIL_MMAP_BLOCK_SIZE, + 0, 0, TRUE); }
--- a/src/lib-index/maildir/maildir-update.c Sun Oct 13 18:52:19 2002 +0300 +++ b/src/lib-index/maildir/maildir-update.c Mon Oct 14 02:49:11 2002 +0300 @@ -1,18 +1,18 @@ /* Copyright (C) 2002 Timo Sirainen */ #include "lib.h" -#include "iobuffer.h" +#include "ibuffer.h" #include "maildir-index.h" int maildir_record_update(MailIndexUpdate *update, int fd, off_t file_size) { - IOBuffer *inbuf; + IBuffer *inbuf; t_push(); - inbuf = io_buffer_create_mmap(fd, data_stack_pool, - MAIL_MMAP_BLOCK_SIZE, 0, file_size, 0); + inbuf = i_buffer_create_mmap(fd, data_stack_pool, MAIL_MMAP_BLOCK_SIZE, + 0, file_size, FALSE); mail_index_update_headers(update, inbuf, 0, NULL, NULL); - io_buffer_unref(inbuf); + i_buffer_unref(inbuf); t_pop(); return TRUE; }
--- a/src/lib-index/mbox/mbox-append.c Sun Oct 13 18:52:19 2002 +0300 +++ b/src/lib-index/mbox/mbox-append.c Mon Oct 14 02:49:11 2002 +0300 @@ -2,7 +2,7 @@ #include "lib.h" #include "ioloop.h" -#include "iobuffer.h" +#include "ibuffer.h" #include "hex-binary.h" #include "md5.h" #include "mbox-index.h" @@ -23,20 +23,21 @@ return rec; } -static int mbox_index_append_next(MailIndex *index, IOBuffer *inbuf) +static int mbox_index_append_next(MailIndex *index, IBuffer *inbuf) { MailIndexRecord *rec; MailIndexUpdate *update; MboxHeaderContext ctx; time_t internal_date; uoff_t abs_start_offset, eoh_offset; - unsigned char *data, md5_digest[16]; + const unsigned char *data; + unsigned char md5_digest[16]; size_t size, pos; int failed; /* get the From-line */ pos = 0; - while (io_buffer_read_data_blocking(inbuf, &data, &size, pos) > 0) { + while (i_buffer_read_data(inbuf, &data, &size, pos) > 0) { for (; pos < size; pos++) { if (data[pos] == '\n') break; @@ -62,13 +63,13 @@ if (internal_date <= 0) internal_date = ioloop_time; - io_buffer_skip(inbuf, pos+1); - abs_start_offset = inbuf->start_offset + inbuf->offset; + i_buffer_skip(inbuf, pos+1); + abs_start_offset = inbuf->start_offset + inbuf->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->offset; + eoh_offset = inbuf->v_offset; /* add message to index */ rec = mail_index_record_append_begin(index, internal_date); @@ -87,13 +88,13 @@ mbox_header_init_context(&ctx, index, inbuf); ctx.set_read_limit = TRUE; - io_buffer_seek(inbuf, abs_start_offset - inbuf->start_offset); + i_buffer_seek(inbuf, abs_start_offset - inbuf->start_offset); - io_buffer_set_read_limit(inbuf, eoh_offset); + i_buffer_set_read_limit(inbuf, eoh_offset); mail_index_update_headers(update, inbuf, 0, mbox_header_func, &ctx); - io_buffer_seek(inbuf, inbuf->limit); - io_buffer_set_read_limit(inbuf, 0); + i_buffer_seek(inbuf, inbuf->v_limit); + i_buffer_set_read_limit(inbuf, 0); /* save MD5 */ md5_final(&ctx.md5, md5_digest); @@ -117,9 +118,9 @@ return !failed; } -int mbox_index_append(MailIndex *index, IOBuffer *inbuf) +int mbox_index_append(MailIndex *index, IBuffer *inbuf) { - if (inbuf->offset == inbuf->size) { + if (inbuf->v_offset == inbuf->v_size) { /* no new data */ return TRUE; } @@ -128,7 +129,7 @@ return FALSE; for (;;) { - if (inbuf->start_offset + inbuf->offset != 0) { + if (inbuf->start_offset + inbuf->v_offset != 0) { /* we're at the [\r]\n before the From-line, skip it */ if (!mbox_skip_crlf(inbuf)) { @@ -142,7 +143,7 @@ } } - if (inbuf->offset == inbuf->size) + if (inbuf->v_offset == inbuf->v_size) break; if (!mbox_index_append_next(index, inbuf))
--- a/src/lib-index/mbox/mbox-fsck.c Sun Oct 13 18:52:19 2002 +0300 +++ b/src/lib-index/mbox/mbox-fsck.c Mon Oct 14 02:49:11 2002 +0300 @@ -1,7 +1,7 @@ /* Copyright (C) 2002 Timo Sirainen */ #include "lib.h" -#include "iobuffer.h" +#include "ibuffer.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(IOBuffer *inbuf) +static void skip_line(IBuffer *inbuf) { - unsigned char *msg; + const unsigned char *msg; size_t i, size; - while (io_buffer_read_data_blocking(inbuf, &msg, &size, 0) > 0) { + while (i_buffer_read_data(inbuf, &msg, &size, 0) > 0) { for (i = 0; i < size; i++) { if (msg[i] == '\n') { - io_buffer_skip(inbuf, i+1); + i_buffer_skip(inbuf, i+1); return; } } - io_buffer_skip(inbuf, i); + i_buffer_skip(inbuf, i); } } @@ -83,7 +83,7 @@ } static int match_next_record(MailIndex *index, MailIndexRecord *rec, - unsigned int seq, IOBuffer *inbuf, + unsigned int seq, IBuffer *inbuf, MailIndexRecord **next_rec, int *dirty) { MailIndexUpdate *update; @@ -97,14 +97,14 @@ /* skip the From-line */ skip_line(inbuf); - header_offset = inbuf->offset; + header_offset = inbuf->v_offset; if (rec->body_size == 0) { /* possibly broken message, find the From-line to make sure header parser won't pass it. */ mbox_skip_header(inbuf); - io_buffer_set_read_limit(inbuf, inbuf->offset); - io_buffer_seek(inbuf, header_offset); + i_buffer_set_read_limit(inbuf, inbuf->v_offset); + i_buffer_seek(inbuf, header_offset); } /* get the MD5 sum of fixed headers and the current message flags @@ -114,9 +114,9 @@ md5_final(&ctx.md5, current_digest); mbox_header_free_context(&ctx); - io_buffer_set_read_limit(inbuf, 0); + i_buffer_set_read_limit(inbuf, 0); - body_offset = inbuf->offset; + body_offset = inbuf->v_offset; do { if (verify_header_md5sum(index, rec, current_digest) && mbox_verify_end_of_body(inbuf, @@ -169,11 +169,11 @@ return TRUE; } -static int mbox_index_fsck_buf(MailIndex *index, IOBuffer *inbuf) +static int mbox_index_fsck_buf(MailIndex *index, IBuffer *inbuf) { MailIndexRecord *rec; uoff_t from_offset; - unsigned char *data; + const unsigned char *data; size_t size; unsigned int seq; int dirty; @@ -185,8 +185,8 @@ /* first make sure we start with a "From " line. If file is too small, we'll just treat it as empty mbox file. */ - if (io_buffer_read_data_blocking(inbuf, &data, &size, 5) > 0 && - strncmp((char *) data, "From ", 5) != 0) { + if (i_buffer_read_data(inbuf, &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); return FALSE; @@ -205,8 +205,8 @@ dirty = FALSE; while (rec != NULL) { - from_offset = inbuf->offset; - if (inbuf->offset != 0) { + from_offset = inbuf->v_offset; + if (inbuf->v_offset != 0) { /* we're at the [\r]\n before the From-line, skip it */ if (!mbox_skip_crlf(inbuf)) { @@ -216,7 +216,7 @@ } } - if (inbuf->offset == inbuf->size) + if (inbuf->v_offset == inbuf->v_size) break; if (!match_next_record(index, rec, seq, inbuf, &rec, &dirty)) @@ -224,7 +224,7 @@ if (rec == NULL) { /* Get back to line before From */ - io_buffer_seek(inbuf, from_offset); + i_buffer_seek(inbuf, from_offset); break; } @@ -244,7 +244,7 @@ index->header->flags &= ~MAIL_INDEX_FLAG_DIRTY_MESSAGES; } - if (inbuf->offset == inbuf->size) + if (inbuf->v_offset == inbuf->v_size) return TRUE; else return mbox_index_append(index, inbuf); @@ -252,7 +252,7 @@ int mbox_index_fsck(MailIndex *index) { - IOBuffer *inbuf; + IBuffer *inbuf; int failed; inbuf = mbox_file_open(index, 0, TRUE); @@ -265,7 +265,7 @@ failed = !mbox_index_fsck_buf(index, inbuf); (void)mbox_unlock(index); } - io_buffer_unref(inbuf); + i_buffer_unref(inbuf); if (failed) return FALSE;
--- a/src/lib-index/mbox/mbox-index.c Sun Oct 13 18:52:19 2002 +0300 +++ b/src/lib-index/mbox/mbox-index.c Mon Oct 14 02:49:11 2002 +0300 @@ -1,7 +1,7 @@ /* Copyright (C) 2002 Timo Sirainen */ #include "lib.h" -#include "iobuffer.h" +#include "ibuffer.h" #include "rfc822-tokenize.h" #include "mbox-index.h" #include "mail-index-util.h" @@ -22,7 +22,7 @@ return FALSE; } -IOBuffer *mbox_file_open(MailIndex *index, uoff_t offset, int reopen) +IBuffer *mbox_file_open(MailIndex *index, uoff_t offset, int reopen) { i_assert(offset < OFF_T_MAX); @@ -37,9 +37,9 @@ } } - return io_buffer_create_mmap(index->mbox_fd, default_pool, - MAIL_MMAP_BLOCK_SIZE, - (uoff_t)offset, 0, 0); + return i_buffer_create_mmap(index->mbox_fd, default_pool, + MAIL_MMAP_BLOCK_SIZE, + (uoff_t)offset, 0, FALSE); } void mbox_file_close(MailIndex *index) @@ -51,7 +51,7 @@ } void mbox_header_init_context(MboxHeaderContext *ctx, MailIndex *index, - IOBuffer *inbuf) + IBuffer *inbuf) { memset(ctx, 0, sizeof(MboxHeaderContext)); md5_init(&ctx->md5); @@ -198,19 +198,19 @@ break; /* a) use Content-Length, b) search for "From "-line */ - start_offset = ctx->inbuf->offset; - io_buffer_set_read_limit(ctx->inbuf, 0); + start_offset = ctx->inbuf->v_offset; + i_buffer_set_read_limit(ctx->inbuf, 0); end_offset = start_offset + ctx->content_length; if (ctx->content_length == 0 || !mbox_verify_end_of_body(ctx->inbuf, end_offset)) { mbox_skip_message(ctx->inbuf); - end_offset = ctx->inbuf->offset; + end_offset = ctx->inbuf->v_offset; ctx->content_length = end_offset - start_offset; } - io_buffer_seek(ctx->inbuf, start_offset); - io_buffer_set_read_limit(ctx->inbuf, end_offset); + i_buffer_seek(ctx->inbuf, start_offset); + i_buffer_set_read_limit(ctx->inbuf, end_offset); break; case 'R': @@ -346,16 +346,16 @@ } } -int mbox_skip_crlf(IOBuffer *inbuf) +int mbox_skip_crlf(IBuffer *inbuf) { - unsigned char *data; + const unsigned char *data; size_t size, pos; pos = 0; - while (io_buffer_read_data_blocking(inbuf, &data, &size, pos) > 0) { + while (i_buffer_read_data(inbuf, &data, &size, pos) > 0) { if (pos == 0) { if (data[0] == '\n') { - io_buffer_skip(inbuf, 1); + i_buffer_skip(inbuf, 1); return TRUE; } if (data[0] != '\r') @@ -368,7 +368,7 @@ if (data[1] != '\n') return FALSE; - io_buffer_skip(inbuf, 2); + i_buffer_skip(inbuf, 2); return TRUE; } } @@ -377,25 +377,25 @@ return TRUE; } -void mbox_skip_empty_lines(IOBuffer *inbuf) +void mbox_skip_empty_lines(IBuffer *inbuf) { - unsigned char *data; + const unsigned char *data; size_t size; /* skip empty lines at beginning */ - while (io_buffer_read_data_blocking(inbuf, &data, &size, 0) > 0 && + while (i_buffer_read_data(inbuf, &data, &size, 0) > 0 && (data[0] == '\r' || data[0] == '\n')) { - io_buffer_skip(inbuf, 1); + i_buffer_skip(inbuf, 1); } } -static int mbox_is_valid_from(IOBuffer *inbuf, size_t startpos) +static int mbox_is_valid_from(IBuffer *inbuf, size_t startpos) { - unsigned char *msg; + const unsigned char *msg; size_t i, size; i = startpos; - while (io_buffer_read_data_blocking(inbuf, &msg, &size, i) > 0) { + while (i_buffer_read_data(inbuf, &msg, &size, i) > 0) { for (; i < size; i++) { if (msg[i] == '\n') { msg += startpos; @@ -409,15 +409,15 @@ return FALSE; } -static void mbox_skip_forward(IOBuffer *inbuf, int header) +static void mbox_skip_forward(IBuffer *inbuf, int header) { - unsigned char *msg; + const unsigned char *msg; size_t i, size, startpos; int lastmsg; /* read until "[\r]\nFrom " is found */ startpos = i = 0; lastmsg = TRUE; - while (io_buffer_read_data_blocking(inbuf, &msg, &size, startpos) > 0) { + while (i_buffer_read_data(inbuf, &msg, &size, startpos) > 0) { for (i = startpos; i < size; i++) { if (msg[i] == '\n' && header && i >= 1) { /* \n[\r]\n - end of header? */ @@ -458,12 +458,12 @@ startpos = i < 7 ? i : 7; i -= startpos; - io_buffer_skip(inbuf, i); + i_buffer_skip(inbuf, i); } if (lastmsg && startpos > 0) { /* end of file, remove the last [\r]\n */ - msg = io_buffer_get_data(inbuf, &size); + msg = i_buffer_get_data(inbuf, &size); if (size == startpos) { if (msg[startpos-1] == '\n') startpos--; @@ -472,36 +472,36 @@ } } - io_buffer_skip(inbuf, startpos); + i_buffer_skip(inbuf, startpos); } -void mbox_skip_header(IOBuffer *inbuf) +void mbox_skip_header(IBuffer *inbuf) { mbox_skip_forward(inbuf, TRUE); } -void mbox_skip_message(IOBuffer *inbuf) +void mbox_skip_message(IBuffer *inbuf) { mbox_skip_forward(inbuf, FALSE); } -int mbox_verify_end_of_body(IOBuffer *inbuf, uoff_t end_offset) +int mbox_verify_end_of_body(IBuffer *inbuf, uoff_t end_offset) { - unsigned char *data; + const unsigned char *data; size_t size; /* don't bother parsing the whole body, just make sure it ends properly */ - io_buffer_seek(inbuf, end_offset); + i_buffer_seek(inbuf, end_offset); - if (inbuf->offset == inbuf->size) { + if (inbuf->v_offset == inbuf->v_size) { /* end of file. a bit unexpected though, since \n is missing. */ return TRUE; } /* read forward a bit */ - if (io_buffer_read_data_blocking(inbuf, &data, &size, 6) < 0) + if (i_buffer_read_data(inbuf, &data, &size, 6) < 0) return FALSE; /* either there should be the next From-line,
--- a/src/lib-index/mbox/mbox-index.h Sun Oct 13 18:52:19 2002 +0300 +++ b/src/lib-index/mbox/mbox-index.h Mon Oct 14 02:49:11 2002 +0300 @@ -11,7 +11,7 @@ MD5Context md5; int received; - IOBuffer *inbuf; + IBuffer *inbuf; uoff_t content_length; int set_read_limit; } MboxHeaderContext; @@ -21,11 +21,11 @@ /* Make sure the mbox is opened. If reopen is TRUE, the file is closed first, which is useful when you want to be sure you're not accessing a deleted mbox file. */ -IOBuffer *mbox_file_open(MailIndex *index, uoff_t offset, int reopen); +IBuffer *mbox_file_open(MailIndex *index, uoff_t offset, int reopen); void mbox_file_close(MailIndex *index); void mbox_header_init_context(MboxHeaderContext *ctx, MailIndex *index, - IOBuffer *inbuf); + IBuffer *inbuf); void mbox_header_free_context(MboxHeaderContext *ctx); void mbox_header_func(MessagePart *part __attr_unused__, const char *name, size_t name_len, @@ -35,11 +35,11 @@ const char *custom_flags[MAIL_CUSTOM_FLAGS_COUNT], void (*func)(const char *, size_t, int, void *), void *context); -int mbox_skip_crlf(IOBuffer *inbuf); -void mbox_skip_empty_lines(IOBuffer *inbuf); -void mbox_skip_header(IOBuffer *inbuf); -void mbox_skip_message(IOBuffer *inbuf); -int mbox_verify_end_of_body(IOBuffer *inbuf, uoff_t end_offset); +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_mail_get_start_offset(MailIndex *index, MailIndexRecord *rec, uoff_t *offset); @@ -47,9 +47,9 @@ int mbox_index_rebuild(MailIndex *index); int mbox_index_sync(MailIndex *index); int mbox_index_fsck(MailIndex *index); -IOBuffer *mbox_open_mail(MailIndex *index, MailIndexRecord *rec); +IBuffer *mbox_open_mail(MailIndex *index, MailIndexRecord *rec); -int mbox_index_append(MailIndex *index, IOBuffer *inbuf); +int mbox_index_append(MailIndex *index, IBuffer *inbuf); 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-open.c Sun Oct 13 18:52:19 2002 +0300 +++ b/src/lib-index/mbox/mbox-open.c Mon Oct 14 02:49:11 2002 +0300 @@ -1,7 +1,7 @@ /* Copyright (C) 2002 Timo Sirainen */ #include "lib.h" -#include "iobuffer.h" +#include "ibuffer.h" #include "mbox-index.h" #include "mail-index-util.h" @@ -9,11 +9,11 @@ #include <unistd.h> #include <fcntl.h> -IOBuffer *mbox_open_mail(MailIndex *index, MailIndexRecord *rec) +IBuffer *mbox_open_mail(MailIndex *index, MailIndexRecord *rec) { - IOBuffer *inbuf; + IBuffer *inbuf; uoff_t offset, stop_offset; - unsigned char *data; + const unsigned char *data; size_t size; int failed; @@ -34,13 +34,14 @@ /* make sure message size is valid - it must end with either EOF or "\nFrom "*/ - if (!io_buffer_seek(inbuf, stop_offset - offset)) { - mbox_set_syscall_error(index, "io_buffer_seek()"); - io_buffer_unref(inbuf); + if (!i_buffer_seek(inbuf, stop_offset - offset)) { + errno = inbuf->buf_errno; + mbox_set_syscall_error(index, "i_buffer_seek()"); + i_buffer_unref(inbuf); return NULL; } - (void)io_buffer_read_data_blocking(inbuf, &data, &size, 6); + (void)i_buffer_read_data(inbuf, &data, &size, 6); if (size >= 6) { /* "[\r]\nFrom " expected */ if (data[0] == '\r') { @@ -48,7 +49,8 @@ size--; } - failed = size < 6 || strncmp((char *) data, "\nFrom ", 6) != 0; + failed = size < 6 || + strncmp((const char *) data, "\nFrom ", 6) != 0; } else { if (size > 0 && data[0] == '\r') { data++; @@ -61,8 +63,9 @@ failed = size != 0; } - if (!io_buffer_seek(inbuf, 0)) { - mbox_set_syscall_error(index, "io_buffer_seek()"); + if (!i_buffer_seek(inbuf, 0)) { + errno = inbuf->buf_errno; + mbox_set_syscall_error(index, "i_buffer_seek()"); failed = TRUE; } @@ -72,10 +75,10 @@ index_set_error(index, "mbox file %s was modified " "unexpectedly, fscking", index->mbox_path); - io_buffer_unref(inbuf); + i_buffer_unref(inbuf); return NULL; } - io_buffer_set_read_limit(inbuf, stop_offset - offset); + i_buffer_set_read_limit(inbuf, stop_offset - offset); return inbuf; }
--- a/src/lib-index/mbox/mbox-rebuild.c Sun Oct 13 18:52:19 2002 +0300 +++ b/src/lib-index/mbox/mbox-rebuild.c Mon Oct 14 02:49:11 2002 +0300 @@ -1,7 +1,7 @@ /* Copyright (C) 2002 Timo Sirainen */ #include "lib.h" -#include "iobuffer.h" +#include "ibuffer.h" #include "mbox-index.h" #include "mbox-lock.h" #include "mail-index-data.h" @@ -14,7 +14,7 @@ int mbox_index_rebuild(MailIndex *index) { - IOBuffer *inbuf; + IBuffer *inbuf; struct stat st; int failed; @@ -48,7 +48,7 @@ /* lock the mailbox so we can be sure no-one interrupts us. */ if (!mbox_lock_read(index)) { - io_buffer_unref(inbuf); + i_buffer_unref(inbuf); return FALSE; } @@ -56,7 +56,7 @@ failed = !mbox_index_append(index, inbuf); (void)mbox_unlock(index); - io_buffer_unref(inbuf); + i_buffer_unref(inbuf); if (failed) return FALSE;
--- a/src/lib-index/mbox/mbox-rewrite.c Sun Oct 13 18:52:19 2002 +0300 +++ b/src/lib-index/mbox/mbox-rewrite.c Mon Oct 14 02:49:11 2002 +0300 @@ -1,7 +1,8 @@ /* Copyright (C) 2002 Timo Sirainen */ #include "lib.h" -#include "iobuffer.h" +#include "ibuffer.h" +#include "obuffer.h" #include "temp-string.h" #include "write-full.h" #include "mbox-index.h" @@ -15,7 +16,7 @@ #include <fcntl.h> typedef struct { - IOBuffer *outbuf; + OBuffer *outbuf; int failed; uoff_t content_length; @@ -48,23 +49,28 @@ MAIL_INDEX_FLAG_DIRTY_CUSTOMFLAGS); } -static int mbox_write(MailIndex *index, IOBuffer *inbuf, IOBuffer *outbuf, +static int mbox_write(MailIndex *index, IBuffer *inbuf, OBuffer *outbuf, uoff_t end_offset) { - i_assert(inbuf->offset <= end_offset); + uoff_t old_limit; + + i_assert(inbuf->v_offset <= end_offset); - if (io_buffer_send_iobuffer(outbuf, inbuf, - end_offset - inbuf->offset) < 0) - return FALSE; - - if (inbuf->offset < end_offset) { + old_limit = inbuf->v_limit; + i_buffer_set_read_limit(inbuf, end_offset - inbuf->v_offset); + if (o_buffer_send_ibuffer(outbuf, inbuf) < 0) { + index_set_error(index, "Error rewriting mbox file %s: %s", + index->mbox_path, strerror(outbuf->buf_errno)); + } else if (inbuf->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); - return FALSE; + } else { + return TRUE; } - return TRUE; + i_buffer_set_read_limit(inbuf, old_limit); + return FALSE; } static int mbox_write_ximapbase(MboxRewriteContext *ctx) @@ -74,21 +80,21 @@ str = t_strdup_printf("X-IMAPbase: %u %u", ctx->uid_validity, ctx->uid_last); - if (io_buffer_send(ctx->outbuf, str, strlen(str)) < 0) + if (o_buffer_send(ctx->outbuf, str, strlen(str)) < 0) return FALSE; for (i = 0; i < MAIL_CUSTOM_FLAGS_COUNT; i++) { if (ctx->custom_flags[i] != NULL) { - if (io_buffer_send(ctx->outbuf, " ", 1) < 0) + if (o_buffer_send(ctx->outbuf, " ", 1) < 0) return FALSE; - if (io_buffer_send(ctx->outbuf, ctx->custom_flags[i], - strlen(ctx->custom_flags[i])) < 0) + if (o_buffer_send(ctx->outbuf, ctx->custom_flags[i], + strlen(ctx->custom_flags[i])) < 0) return FALSE; } } - if (io_buffer_send(ctx->outbuf, "\n", 1) < 0) + if (o_buffer_send(ctx->outbuf, "\n", 1) < 0) return FALSE; return TRUE; @@ -103,32 +109,32 @@ x_keywords == NULL) return TRUE; - if (io_buffer_send(ctx->outbuf, "X-Keywords:", 11) < 0) + if (o_buffer_send(ctx->outbuf, "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 (io_buffer_send(ctx->outbuf, " ", 1) < 0) + if (o_buffer_send(ctx->outbuf, " ", 1) < 0) return FALSE; - if (io_buffer_send(ctx->outbuf, ctx->custom_flags[i], - strlen(ctx->custom_flags[i])) < 0) + if (o_buffer_send(ctx->outbuf, ctx->custom_flags[i], + strlen(ctx->custom_flags[i])) < 0) return FALSE; } } if (x_keywords != NULL) { /* X-Keywords that aren't custom flags */ - if (io_buffer_send(ctx->outbuf, " ", 1) < 0) + if (o_buffer_send(ctx->outbuf, " ", 1) < 0) return FALSE; - if (io_buffer_send(ctx->outbuf, x_keywords, - strlen(x_keywords)) < 0) + if (o_buffer_send(ctx->outbuf, x_keywords, + strlen(x_keywords)) < 0) return FALSE; } - if (io_buffer_send(ctx->outbuf, "\n", 1) < 0) + if (o_buffer_send(ctx->outbuf, "\n", 1) < 0) return FALSE; return TRUE; @@ -142,9 +148,9 @@ if (status != NULL) str = t_strconcat(str, status, NULL); - if (io_buffer_send(ctx->outbuf, str, strlen(str)) < 0) + if (o_buffer_send(ctx->outbuf, str, strlen(str)) < 0) return FALSE; - if (io_buffer_send(ctx->outbuf, "\n", 1) < 0) + if (o_buffer_send(ctx->outbuf, "\n", 1) < 0) return FALSE; return TRUE; @@ -166,9 +172,9 @@ (ctx->msg_flags & MAIL_DELETED) ? "T" : "", x_status, NULL); - if (io_buffer_send(ctx->outbuf, str, strlen(str)) < 0) + if (o_buffer_send(ctx->outbuf, str, strlen(str)) < 0) return FALSE; - if (io_buffer_send(ctx->outbuf, "\n", 1) < 0) + if (o_buffer_send(ctx->outbuf, "\n", 1) < 0) return FALSE; return TRUE; @@ -181,7 +187,7 @@ i_snprintf(str, sizeof(str), "Content-Length: %"PRIuUOFF_T"\n", ctx->content_length); - if (io_buffer_send(ctx->outbuf, str, strlen(str)) < 0) + if (o_buffer_send(ctx->outbuf, str, strlen(str)) < 0) return FALSE; return TRUE; } @@ -274,10 +280,10 @@ (void)mbox_write_content_length(ctx); } else if (name_len > 0) { /* save this header */ - (void)io_buffer_send(ctx->outbuf, name, name_len); - (void)io_buffer_send(ctx->outbuf, ": ", 2); - (void)io_buffer_send(ctx->outbuf, value, value_len); - (void)io_buffer_send(ctx->outbuf, "\n", 1); + (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); } if (ctx->outbuf->closed) @@ -286,7 +292,7 @@ static int mbox_write_header(MailIndex *index, MailIndexRecord *rec, unsigned int seq, - IOBuffer *inbuf, IOBuffer *outbuf, + IBuffer *inbuf, OBuffer *outbuf, uoff_t end_offset) { /* We need to update fields that define message flags. Standard fields @@ -303,7 +309,7 @@ MboxRewriteContext ctx; MessageSize hdr_size; - if (inbuf->offset >= end_offset) { + if (inbuf->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); @@ -321,9 +327,9 @@ ctx.uid_validity = index->header->uid_validity-1; ctx.custom_flags = mail_custom_flags_list_get(index->custom_flags); - io_buffer_set_read_limit(inbuf, inbuf->offset + rec->header_size); + i_buffer_set_read_limit(inbuf, inbuf->v_offset + rec->header_size); message_parse_header(NULL, inbuf, &hdr_size, header_func, &ctx); - io_buffer_set_read_limit(inbuf, 0); + i_buffer_set_read_limit(inbuf, 0); i_assert(hdr_size.physical_size == rec->header_size); @@ -347,14 +353,15 @@ mail_custom_flags_list_unref(index->custom_flags); /* empty line ends headers */ - (void)io_buffer_send(outbuf, "\n", 1); + (void)o_buffer_send(outbuf, "\n", 1); return TRUE; } static int fd_copy(int in_fd, int out_fd, uoff_t out_offset) { - IOBuffer *inbuf, *outbuf; + IBuffer *inbuf; + OBuffer *outbuf; int ret; i_assert(out_offset <= OFF_T_MAX); @@ -364,21 +371,22 @@ t_push(); - inbuf = io_buffer_create_mmap(in_fd, data_stack_pool, - 1024*256, 0, 0, 0); - outbuf = io_buffer_create_file(out_fd, data_stack_pool, 1024, FALSE); + inbuf = i_buffer_create_mmap(in_fd, data_stack_pool, + 1024*256, 0, 0, FALSE); + outbuf = o_buffer_create_file(out_fd, data_stack_pool, 1024, + IO_PRIORITY_DEFAULT, FALSE); - ret = io_buffer_send_iobuffer(outbuf, inbuf, inbuf->size); + ret = o_buffer_send_ibuffer(outbuf, inbuf); if (ret < 0) errno = outbuf->buf_errno; else { /* we may have shrinked the file */ - i_assert(out_offset + inbuf->size <= OFF_T_MAX); - ret = ftruncate(out_fd, (off_t) (out_offset + inbuf->size)); + i_assert(out_offset + inbuf->v_size <= OFF_T_MAX); + ret = ftruncate(out_fd, (off_t) (out_offset + inbuf->v_size)); } - io_buffer_unref(outbuf); - io_buffer_unref(inbuf); + o_buffer_unref(outbuf); + i_buffer_unref(inbuf); t_pop(); return ret; @@ -391,7 +399,8 @@ interrupted (see below). This rewriting relies quite a lot on valid header/body sizes which fsck() should have ensured. */ MailIndexRecord *rec; - IOBuffer *inbuf, *outbuf; + IBuffer *inbuf; + OBuffer *outbuf; uoff_t offset, dirty_offset; const char *path; unsigned int seq; @@ -439,7 +448,7 @@ if (locked) (void)mbox_unlock(index); if (inbuf != NULL) - io_buffer_unref(inbuf); + i_buffer_unref(inbuf); return !failed; } @@ -452,7 +461,8 @@ dirty_offset = 0; t_push(); - outbuf = io_buffer_create_file(tmp_fd, data_stack_pool, 8192, FALSE); + outbuf = o_buffer_create_file(tmp_fd, data_stack_pool, 8192, + IO_PRIORITY_DEFAULT, FALSE); failed = FALSE; seq = 1; rec = index->lookup(index, 1); @@ -465,7 +475,8 @@ break; } - if (offset + rec->header_size + rec->body_size > inbuf->size) { + if (offset + rec->header_size + + rec->body_size > inbuf->v_size) { index_set_corrupted(index, "Invalid message size"); failed = TRUE; @@ -481,7 +492,7 @@ dirty_found = TRUE; dirty_offset = offset; - io_buffer_seek(inbuf, dirty_offset); + i_buffer_seek(inbuf, dirty_offset); } if (dirty_found) { @@ -518,15 +529,15 @@ } /* always end with a \n */ - (void)io_buffer_send(outbuf, "\n", 1); + (void)o_buffer_send(outbuf, "\n", 1); if (outbuf->closed) { errno = outbuf->buf_errno; mbox_set_syscall_error(index, "write()"); failed = TRUE; } - io_buffer_unref(inbuf); - io_buffer_unref(outbuf); + i_buffer_unref(inbuf); + o_buffer_unref(outbuf); t_pop(); if (!failed) {
--- a/src/lib-index/mbox/mbox-sync.c Sun Oct 13 18:52:19 2002 +0300 +++ b/src/lib-index/mbox/mbox-sync.c Mon Oct 14 02:49:11 2002 +0300 @@ -1,7 +1,6 @@ /* Copyright (C) 2002 Timo Sirainen */ #include "lib.h" -#include "iobuffer.h" #include "mbox-index.h" #include "mail-index-util.h"
--- a/src/lib-mail/message-parser.c Sun Oct 13 18:52:19 2002 +0300 +++ b/src/lib-mail/message-parser.c Mon Oct 14 02:49:11 2002 +0300 @@ -1,7 +1,7 @@ /* Copyright (C) 2002 Timo Sirainen */ #include "lib.h" -#include "iobuffer.h" +#include "ibuffer.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(IOBuffer *inbuf, +static MessagePart *message_parse_part(IBuffer *inbuf, MessageParseContext *parse_ctx); -static MessagePart *message_parse_body(IOBuffer *inbuf, +static MessagePart *message_parse_body(IBuffer *inbuf, MessageBoundary *boundaries, MessageSize *body_size); -static MessagePart *message_skip_boundary(IOBuffer *inbuf, +static MessagePart *message_skip_boundary(IBuffer *inbuf, MessageBoundary *boundaries, MessageSize *boundary_size); @@ -136,7 +136,7 @@ } } -static MessagePart *message_parse_multipart(IOBuffer *inbuf, +static MessagePart *message_parse_multipart(IBuffer *inbuf, MessageParseContext *parse_ctx) { MessagePart *parent_part, *next_part, *part; @@ -185,7 +185,7 @@ return next_part; } -static MessagePart *message_parse_part(IOBuffer *inbuf, +static MessagePart *message_parse_part(IBuffer *inbuf, MessageParseContext *parse_ctx) { MessagePart *next_part, *part; @@ -241,7 +241,7 @@ return next_part; } -MessagePart *message_parse(Pool pool, IOBuffer *inbuf, +MessagePart *message_parse(Pool pool, IBuffer *inbuf, MessageHeaderFunc func, void *context) { MessagePart *part; @@ -260,14 +260,14 @@ } /* skip over to next line increasing message size */ -static void message_skip_line(IOBuffer *inbuf, MessageSize *msg_size) +static void message_skip_line(IBuffer *inbuf, MessageSize *msg_size) { - unsigned char *msg; + const unsigned char *msg; size_t i, size, startpos; startpos = 0; - while (io_buffer_read_data_blocking(inbuf, &msg, &size, startpos) > 0) { + while (i_buffer_read_data(inbuf, &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 */ - io_buffer_skip(inbuf, i - 1); + i_buffer_skip(inbuf, i - 1); startpos = 1; if (msg_size != NULL) { @@ -294,7 +294,7 @@ } } - io_buffer_skip(inbuf, startpos); + i_buffer_skip(inbuf, startpos); if (msg_size != NULL) { msg_size->physical_size += startpos; @@ -302,11 +302,11 @@ } } -void message_parse_header(MessagePart *part, IOBuffer *inbuf, +void message_parse_header(MessagePart *part, IBuffer *inbuf, MessageSize *hdr_size, MessageHeaderFunc func, void *context) { - unsigned char *msg; + const unsigned char *msg; size_t i, size, startpos, missing_cr_count; size_t line_start, colon_pos, end_pos, name_len, value_len; int ret; @@ -317,8 +317,7 @@ missing_cr_count = startpos = line_start = 0; colon_pos = UINT_MAX; for (;;) { - ret = io_buffer_read_data_blocking(inbuf, &msg, &size, - startpos+1); + ret = i_buffer_read_data(inbuf, &msg, &size, startpos+1); if (ret == -2) { /* overflow, line is too long. just skip it. */ i_assert(size > 2); @@ -411,13 +410,13 @@ colon_pos -= line_start; if (hdr_size != NULL) hdr_size->physical_size += line_start; - io_buffer_skip(inbuf, line_start); + i_buffer_skip(inbuf, line_start); startpos = i-line_start; line_start = 0; } - io_buffer_skip(inbuf, startpos); + i_buffer_skip(inbuf, startpos); if (hdr_size != NULL) { hdr_size->physical_size += startpos; @@ -450,17 +449,17 @@ [\r]\n before the boundary, otherwise leave it right after the known boundary so the ending "--" can be checked. */ static MessageBoundary * -message_find_boundary(IOBuffer *inbuf, MessageBoundary *boundaries, +message_find_boundary(IBuffer *inbuf, MessageBoundary *boundaries, MessageSize *msg_size, int skip_over) { MessageBoundary *boundary; - unsigned char *msg; + const unsigned char *msg; size_t i, size, startpos, line_start, missing_cr_count; boundary = NULL; missing_cr_count = startpos = line_start = 0; - while (io_buffer_read_data_blocking(inbuf, &msg, &size, startpos) > 0) { + while (i_buffer_read_data(inbuf, &msg, &size, startpos) > 0) { for (i = startpos; i < size; i++) { if (msg[i] != '\n') continue; @@ -510,7 +509,7 @@ line_start -= i; } - io_buffer_skip(inbuf, i); + i_buffer_skip(inbuf, i); msg_size->physical_size += i; msg_size->virtual_size += i; @@ -534,7 +533,7 @@ startpos = line_start; } - io_buffer_skip(inbuf, startpos); + i_buffer_skip(inbuf, startpos); msg_size->physical_size += startpos; msg_size->virtual_size += startpos + missing_cr_count; @@ -543,7 +542,7 @@ return boundary; } -static MessagePart *message_parse_body(IOBuffer *inbuf, +static MessagePart *message_parse_body(IBuffer *inbuf, MessageBoundary *boundaries, MessageSize *body_size) { @@ -561,12 +560,12 @@ /* skip data until next boundary is found. if it's end boundary, skip the footer as well. */ -static MessagePart *message_skip_boundary(IOBuffer *inbuf, +static MessagePart *message_skip_boundary(IBuffer *inbuf, MessageBoundary *boundaries, MessageSize *boundary_size) { MessageBoundary *boundary; - unsigned char *msg; + const unsigned char *msg; size_t size; int end_boundary; @@ -577,7 +576,7 @@ /* now, see if it's end boundary */ end_boundary = FALSE; - if (io_buffer_read_data_blocking(inbuf, &msg, &size, 1) > 0) + if (i_buffer_read_data(inbuf, &msg, &size, 1) > 0) end_boundary = msg[0] == '-' && msg[1] == '-'; /* skip the rest of the line */
--- a/src/lib-mail/message-parser.h Sun Oct 13 18:52:19 2002 +0300 +++ b/src/lib-mail/message-parser.h Mon Oct 14 02:49:11 2002 +0300 @@ -44,7 +44,7 @@ void *context); /* func is called for each field in message header. */ -MessagePart *message_parse(Pool pool, IOBuffer *inbuf, +MessagePart *message_parse(Pool pool, IBuffer *inbuf, MessageHeaderFunc func, void *context); /* Call func for each field in message header. Fills the hdr_size. @@ -52,7 +52,7 @@ 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 body. */ -void message_parse_header(MessagePart *part, IOBuffer *inbuf, +void message_parse_header(MessagePart *part, IBuffer *inbuf, MessageSize *hdr_size, MessageHeaderFunc func, void *context);
--- a/src/lib-mail/message-send.c Sun Oct 13 18:52:19 2002 +0300 +++ b/src/lib-mail/message-send.c Mon Oct 14 02:49:11 2002 +0300 @@ -1,16 +1,18 @@ /* Copyright (C) 2002 Timo Sirainen */ #include "lib.h" -#include "iobuffer.h" +#include "ibuffer.h" +#include "obuffer.h" #include "message-send.h" #include "message-size.h" -int message_send(IOBuffer *outbuf, IOBuffer *inbuf, MessageSize *msg_size, +int message_send(OBuffer *outbuf, IBuffer *inbuf, MessageSize *msg_size, uoff_t virtual_skip, uoff_t max_virtual_size) { - unsigned char *msg; + const unsigned char *msg; + uoff_t old_limit; size_t i, size; - int cr_skipped, add_cr; + int cr_skipped, add_cr, ret; if (msg_size->physical_size == 0 || virtual_skip >= msg_size->virtual_size) @@ -21,15 +23,21 @@ if (msg_size->physical_size == msg_size->virtual_size) { /* no need to kludge with CRs, we can use sendfile() */ - io_buffer_skip(inbuf, virtual_skip); - return io_buffer_send_iobuffer(outbuf, inbuf, - max_virtual_size) > 0; + i_buffer_skip(inbuf, virtual_skip); + + old_limit = inbuf->v_limit; + i_buffer_set_read_limit(inbuf, + I_MIN(max_virtual_size, old_limit)); + ret = o_buffer_send_ibuffer(outbuf, inbuf) > 0; + i_buffer_set_read_limit(inbuf, old_limit); + + return ret; } message_skip_virtual(inbuf, virtual_skip, NULL, &cr_skipped); /* go through the message data and insert CRs where needed. */ - while (io_buffer_read_data_blocking(inbuf, &msg, &size, 0) > 0) { + while (i_buffer_read_data(inbuf, &msg, &size, 0) > 0) { add_cr = FALSE; for (i = 0; i < size; i++) { if (msg[i] == '\n') { @@ -52,11 +60,11 @@ } } - if (io_buffer_send(outbuf, msg, i) <= 0) + if (o_buffer_send(outbuf, msg, i) <= 0) return FALSE; if (add_cr) { - if (io_buffer_send(outbuf, "\r", 1) <= 0) + if (o_buffer_send(outbuf, "\r", 1) <= 0) return FALSE; cr_skipped = TRUE; } else { @@ -67,7 +75,7 @@ if (max_virtual_size == 0) break; - io_buffer_skip(inbuf, i); + i_buffer_skip(inbuf, i); } return TRUE;
--- a/src/lib-mail/message-send.h Sun Oct 13 18:52:19 2002 +0300 +++ b/src/lib-mail/message-send.h Mon Oct 14 02:49:11 2002 +0300 @@ -6,7 +6,7 @@ /* 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. Returns TRUE if successful. */ -int message_send(IOBuffer *outbuf, IOBuffer *inbuf, MessageSize *msg_size, +int message_send(OBuffer *outbuf, IBuffer *inbuf, MessageSize *msg_size, uoff_t virtual_skip, uoff_t max_virtual_size); #endif
--- a/src/lib-mail/message-size.c Sun Oct 13 18:52:19 2002 +0300 +++ b/src/lib-mail/message-size.c Mon Oct 14 02:49:11 2002 +0300 @@ -1,19 +1,19 @@ /* Copyright (C) 2002 Timo Sirainen */ #include "lib.h" -#include "iobuffer.h" +#include "ibuffer.h" #include "message-parser.h" #include "message-size.h" -void message_get_header_size(IOBuffer *inbuf, MessageSize *hdr) +void message_get_header_size(IBuffer *inbuf, MessageSize *hdr) { - unsigned char *msg; + const unsigned char *msg; size_t i, size, startpos, missing_cr_count; memset(hdr, 0, sizeof(MessageSize)); missing_cr_count = 0; startpos = 0; - while (io_buffer_read_data_blocking(inbuf, &msg, &size, startpos) > 0) { + while (i_buffer_read_data(inbuf, &msg, &size, startpos) > 0) { for (i = startpos; i < size; i++) { if (msg[i] != '\n') continue; @@ -44,28 +44,28 @@ /* leave the last two characters, they may be \r\n */ startpos = size == 1 ? 1 : 2; - io_buffer_skip(inbuf, i - startpos); + i_buffer_skip(inbuf, i - startpos); hdr->physical_size += i - startpos; } - io_buffer_skip(inbuf, startpos); + i_buffer_skip(inbuf, 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(IOBuffer *inbuf, MessageSize *body, +void message_get_body_size(IBuffer *inbuf, MessageSize *body, uoff_t max_virtual_size) { - unsigned char *msg; + const unsigned char *msg; size_t i, size, startpos, missing_cr_count; memset(body, 0, sizeof(MessageSize)); missing_cr_count = 0; startpos = 0; while (max_virtual_size != 0 && - io_buffer_read_data_blocking(inbuf, &msg, &size, startpos) > 0) { + i_buffer_read_data(inbuf, &msg, &size, startpos) > 0) { for (i = startpos; i < size && max_virtual_size != 0; i++) { if (max_virtual_size > 0) max_virtual_size--; @@ -91,22 +91,22 @@ } /* leave the last character, it may be \r */ - io_buffer_skip(inbuf, i - 1); + i_buffer_skip(inbuf, i - 1); startpos = 1; body->physical_size += i - 1; } - io_buffer_skip(inbuf, startpos); + i_buffer_skip(inbuf, 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(IOBuffer *inbuf, uoff_t virtual_skip, +void message_skip_virtual(IBuffer *inbuf, uoff_t virtual_skip, MessageSize *msg_size, int *cr_skipped) { - unsigned char *msg; + const unsigned char *msg; size_t i, size, startpos; *cr_skipped = FALSE; @@ -114,7 +114,7 @@ return; startpos = 0; - while (io_buffer_read_data_blocking(inbuf, &msg, &size, startpos) > 0) { + while (i_buffer_read_data(inbuf, &msg, &size, startpos) > 0) { for (i = startpos; i < size && virtual_skip > 0; i++) { virtual_skip--; @@ -151,12 +151,12 @@ } if (i < size) { - io_buffer_skip(inbuf, i); + i_buffer_skip(inbuf, i); break; } /* leave the last character, it may be \r */ - io_buffer_skip(inbuf, i - 1); + i_buffer_skip(inbuf, i - 1); startpos = 1; } }
--- a/src/lib-mail/message-size.h Sun Oct 13 18:52:19 2002 +0300 +++ b/src/lib-mail/message-size.h Mon Oct 14 02:49:11 2002 +0300 @@ -5,16 +5,16 @@ /* Calculate size of message header. Leave the inbuf point to first character in body. */ -void message_get_header_size(IOBuffer *inbuf, MessageSize *hdr); +void message_get_header_size(IBuffer *inbuf, 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(IOBuffer *inbuf, MessageSize *body, +void message_get_body_size(IBuffer *inbuf, MessageSize *body, uoff_t max_virtual_size); /* Skip number of virtual bytes from buffer. 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(IOBuffer *inbuf, uoff_t virtual_skip, +void message_skip_virtual(IBuffer *inbuf, uoff_t virtual_skip, MessageSize *msg_size, int *cr_skipped); /* Sum contents of src into dest. */
--- a/src/lib-storage/index/index-copy.c Sun Oct 13 18:52:19 2002 +0300 +++ b/src/lib-storage/index/index-copy.c Mon Oct 14 02:49:11 2002 +0300 @@ -1,7 +1,7 @@ /* Copyright (C) 2002 Timo Sirainen */ #include "lib.h" -#include "iobuffer.h" +#include "ibuffer.h" #include "mail-custom-flags.h" #include "index-storage.h" #include "index-messageset.h" @@ -18,7 +18,7 @@ unsigned int idx_seq __attr_unused__, void *context) { CopyContext *ctx = context; - IOBuffer *inbuf; + IBuffer *inbuf; int failed; inbuf = index->open_mail(index, rec); @@ -28,9 +28,9 @@ /* save it in destination mailbox */ failed = !ctx->dest->save(ctx->dest, rec->msg_flags, ctx->custom_flags, rec->internal_date, - inbuf, inbuf->size); + inbuf, inbuf->v_size); - io_buffer_unref(inbuf); + i_buffer_unref(inbuf); return !failed; }
--- a/src/lib-storage/index/index-fetch-section.c Sun Oct 13 18:52:19 2002 +0300 +++ b/src/lib-storage/index/index-fetch-section.c Mon Oct 14 02:49:11 2002 +0300 @@ -2,7 +2,8 @@ #include "lib.h" #include "temp-string.h" -#include "iobuffer.h" +#include "ibuffer.h" +#include "obuffer.h" #include "rfc822-tokenize.h" #include "message-send.h" #include "index-storage.h" @@ -42,7 +43,7 @@ FetchContext *ctx, const char *prefix, int fetch_header) { MessageSize size; - IOBuffer *inbuf; + IBuffer *inbuf; const char *str; if (!imap_msgcache_get_rfc822_partial(ctx->cache, sect->skip, @@ -55,7 +56,7 @@ str = t_strdup_printf("%s {%"PRIuUOFF_T"}\r\n", prefix, size.virtual_size); - if (io_buffer_send(ctx->outbuf, str, strlen(str)) < 0) + if (o_buffer_send(ctx->outbuf, str, strlen(str)) < 0) return FALSE; return message_send(ctx->outbuf, inbuf, &size, 0, sect->max_size); @@ -133,7 +134,7 @@ typedef struct { TempString *dest; - IOBuffer *outbuf; + OBuffer *outbuf; uoff_t dest_size; uoff_t skip, max_size; @@ -165,7 +166,7 @@ ctx->dest_size += size; if (ctx->outbuf != NULL) { - if (io_buffer_send(ctx->outbuf, str, size) < 0) + if (o_buffer_send(ctx->outbuf, str, size) < 0) return FALSE; } return ctx->dest_size < ctx->max_size; @@ -214,7 +215,7 @@ (void)fetch_header_append(ctx, "\r\n", 2); } -static int fetch_header_fields(IOBuffer *inbuf, const char *section, +static int fetch_header_fields(IBuffer *inbuf, const char *section, FetchHeaderFieldContext *ctx) { if (strncasecmp(section, "HEADER.FIELDS ", 14) == 0) { @@ -240,7 +241,7 @@ } /* fetch wanted headers from given data */ -static int fetch_header_from(IOBuffer *inbuf, IOBuffer *outbuf, +static int fetch_header_from(IBuffer *inbuf, OBuffer *outbuf, const char *prefix, MessageSize *size, const char *section, MailFetchBodyData *sect) { @@ -255,7 +256,7 @@ /* all headers */ str = t_strdup_printf("%s {%"PRIuUOFF_T"}\r\n", prefix, size->virtual_size); - if (io_buffer_send(outbuf, str, strlen(str)) < 0) + if (o_buffer_send(outbuf, str, strlen(str)) < 0) return FALSE; return message_send(outbuf, inbuf, size, sect->skip, sect->max_size); @@ -270,7 +271,7 @@ ctx.max_size = sect->max_size; failed = FALSE; - start_offset = inbuf->offset; + start_offset = inbuf->v_offset; t_push(); @@ -291,7 +292,7 @@ if (!failed) { str = t_strdup_printf("%s {%"PRIuUOFF_T"}\r\n", prefix, ctx.dest_size); - if (io_buffer_send(outbuf, str, strlen(str)) < 0) + if (o_buffer_send(outbuf, str, strlen(str)) < 0) failed = TRUE; } @@ -301,7 +302,7 @@ uoff_t first_size = ctx.dest_size; ctx.outbuf = outbuf; - if (!io_buffer_seek(inbuf, start_offset)) + if (!i_buffer_seek(inbuf, start_offset)) failed = TRUE; if (!failed && @@ -310,8 +311,8 @@ i_assert(first_size == ctx.dest_size); } else { - if (io_buffer_send(outbuf, ctx.dest->str, - ctx.dest->len) < 0) + if (o_buffer_send(outbuf, ctx.dest->str, + ctx.dest->len) < 0) failed = TRUE; } } @@ -325,7 +326,7 @@ const char *prefix) { MessageSize hdr_size; - IOBuffer *inbuf; + IBuffer *inbuf; if (!imap_msgcache_get_rfc822(ctx->cache, &inbuf, &hdr_size, NULL)) return FALSE; @@ -378,7 +379,7 @@ static int fetch_part_body(MessagePart *part, MailFetchBodyData *sect, FetchContext *ctx, const char *prefix) { - IOBuffer *inbuf; + IBuffer *inbuf; const char *str; uoff_t skip_pos; @@ -387,11 +388,11 @@ /* jump to beginning of wanted data */ skip_pos = part->physical_pos + part->header_size.physical_size; - io_buffer_skip(inbuf, skip_pos); + i_buffer_skip(inbuf, skip_pos); str = t_strdup_printf("%s {%"PRIuUOFF_T"}\r\n", prefix, part->body_size.virtual_size); - if (io_buffer_send(ctx->outbuf, str, strlen(str)) < 0) + if (o_buffer_send(ctx->outbuf, str, strlen(str)) < 0) return FALSE; /* FIXME: potential performance problem with big messages: @@ -405,12 +406,12 @@ MailFetchBodyData *sect, FetchContext *ctx, const char *prefix) { - IOBuffer *inbuf; + IBuffer *inbuf; if (!imap_msgcache_get_data(ctx->cache, &inbuf)) return FALSE; - io_buffer_skip(inbuf, part->physical_pos); + i_buffer_skip(inbuf, part->physical_pos); return fetch_header_from(inbuf, ctx->outbuf, prefix, &part->header_size, section, sect); }
--- a/src/lib-storage/index/index-fetch.c Sun Oct 13 18:52:19 2002 +0300 +++ b/src/lib-storage/index/index-fetch.c Mon Oct 14 02:49:11 2002 +0300 @@ -1,7 +1,7 @@ /* Copyright (C) 2002 Timo Sirainen */ #include "lib.h" -#include "iobuffer.h" +#include "obuffer.h" #include "temp-string.h" #include "mail-custom-flags.h" #include "index-storage.h" @@ -108,7 +108,7 @@ static int index_fetch_send_rfc822(MailIndexRecord *rec, FetchContext *ctx) { MessageSize hdr_size, body_size; - IOBuffer *inbuf; + IBuffer *inbuf; const char *str; if (!imap_msgcache_get_rfc822(ctx->cache, &inbuf, @@ -124,7 +124,7 @@ if (ctx->first) { str++; ctx->first = FALSE; } - if (io_buffer_send(ctx->outbuf, str, strlen(str)) < 0) + if (o_buffer_send(ctx->outbuf, str, strlen(str)) < 0) return FALSE; body_size.physical_size += hdr_size.physical_size; @@ -136,7 +136,7 @@ FetchContext *ctx) { MessageSize hdr_size; - IOBuffer *inbuf; + IBuffer *inbuf; const char *str; if (!imap_msgcache_get_rfc822(ctx->cache, &inbuf, &hdr_size, NULL)) { @@ -151,7 +151,7 @@ if (ctx->first) { str++; ctx->first = FALSE; } - if (io_buffer_send(ctx->outbuf, str, strlen(str)) < 0) + if (o_buffer_send(ctx->outbuf, str, strlen(str)) < 0) return FALSE; return message_send(ctx->outbuf, inbuf, &hdr_size, 0, (uoff_t)-1); @@ -160,7 +160,7 @@ static int index_fetch_send_rfc822_text(MailIndexRecord *rec, FetchContext *ctx) { MessageSize body_size; - IOBuffer *inbuf; + IBuffer *inbuf; const char *str; if (!imap_msgcache_get_rfc822(ctx->cache, &inbuf, NULL, &body_size)) { @@ -175,7 +175,7 @@ if (ctx->first) { str++; ctx->first = FALSE; } - if (io_buffer_send(ctx->outbuf, str, strlen(str)) < 0) + if (o_buffer_send(ctx->outbuf, str, strlen(str)) < 0) return FALSE; return message_send(ctx->outbuf, inbuf, &body_size, 0, (uoff_t)-1); @@ -299,8 +299,8 @@ if (!ctx->first) ctx->str->len--; - if (io_buffer_send(ctx->outbuf, ctx->str->str, - ctx->str->len) < 0) + if (o_buffer_send(ctx->outbuf, ctx->str->str, + ctx->str->len) < 0) break; } @@ -327,7 +327,7 @@ } while (0); if (data_written) { - if (io_buffer_send(ctx->outbuf, ")\r\n", 3) < 0) + if (o_buffer_send(ctx->outbuf, ")\r\n", 3) < 0) failed = TRUE; } @@ -336,7 +336,7 @@ } int index_storage_fetch(Mailbox *box, MailFetchData *fetch_data, - IOBuffer *outbuf, int *all_found) + OBuffer *outbuf, int *all_found) { IndexMailbox *ibox = (IndexMailbox *) box; FetchContext ctx;
--- a/src/lib-storage/index/index-fetch.h Sun Oct 13 18:52:19 2002 +0300 +++ b/src/lib-storage/index/index-fetch.h Mon Oct 14 02:49:11 2002 +0300 @@ -9,7 +9,7 @@ const char **custom_flags; MailFetchData *fetch_data; - IOBuffer *outbuf; + OBuffer *outbuf; TempString *str; int update_seen, found_unseen; int first;
--- a/src/lib-storage/index/index-msgcache.c Sun Oct 13 18:52:19 2002 +0300 +++ b/src/lib-storage/index/index-msgcache.c Mon Oct 14 02:49:11 2002 +0300 @@ -1,7 +1,7 @@ /* Copyright (C) 2002 Timo Sirainen */ #include "lib.h" -#include "iobuffer.h" +#include "ibuffer.h" #include "imap-message-cache.h" #include "message-part-serialize.h" #include "mail-index.h" @@ -24,20 +24,20 @@ return ctx; } -static IOBuffer *index_msgcache_open_mail(void *context) +static IBuffer *index_msgcache_open_mail(void *context) { IndexMsgcacheContext *ctx = context; return ctx->index->open_mail(ctx->index, ctx->rec); } -static IOBuffer *index_msgcache_inbuf_rewind(IOBuffer *inbuf, - void *context __attr_unused__) +static IBuffer *index_msgcache_inbuf_rewind(IBuffer *inbuf, + void *context __attr_unused__) { - if (!io_buffer_seek(inbuf, 0)) { + if (!i_buffer_seek(inbuf, 0)) { i_error("index_msgcache_inbuf_rewind: lseek() failed: %m"); - io_buffer_unref(inbuf); + i_buffer_unref(inbuf); return NULL; }
--- a/src/lib-storage/index/index-save.c Sun Oct 13 18:52:19 2002 +0300 +++ b/src/lib-storage/index/index-save.c Mon Oct 14 02:49:11 2002 +0300 @@ -1,7 +1,7 @@ /* Copyright (C) 2002 Timo Sirainen */ #include "lib.h" -#include "iobuffer.h" +#include "ibuffer.h" #include "write-full.h" #include "index-storage.h" @@ -38,9 +38,9 @@ } int index_storage_save_into_fd(MailStorage *storage, int fd, const char *path, - IOBuffer *buf, uoff_t data_size) + IBuffer *buf, uoff_t data_size) { - unsigned char *data; + const unsigned char *data; size_t size; ssize_t ret; int last_cr, failed; @@ -49,14 +49,14 @@ failed = FALSE; while (data_size > 0) { - ret = io_buffer_read_blocking(buf); + ret = i_buffer_read(buf); if (ret < 0) { mail_storage_set_critical(storage, "Error reading mail: %m"); return FALSE; } - data = io_buffer_get_data(buf, &size); + data = i_buffer_get_data(buf, &size); if (size > data_size) size = (size_t)data_size; data_size -= size; @@ -73,7 +73,7 @@ failed = TRUE; } - io_buffer_skip(buf, size); + i_buffer_skip(buf, size); } return !failed;
--- a/src/lib-storage/index/index-search.c Sun Oct 13 18:52:19 2002 +0300 +++ b/src/lib-storage/index/index-search.c Mon Oct 14 02:49:11 2002 +0300 @@ -1,7 +1,8 @@ /* Copyright (C) 2002 Timo Sirainen */ #include "lib.h" -#include "iobuffer.h" +#include "ibuffer.h" +#include "obuffer.h" #include "mmap-util.h" #include "rfc822-tokenize.h" #include "rfc822-date.h" @@ -530,12 +531,12 @@ search_text(arg, ctx); } -static void search_arg_match_data(IOBuffer *inbuf, uoff_t max_size, +static void search_arg_match_data(IBuffer *inbuf, uoff_t max_size, MailSearchArg *args, MailSearchForeachFunc search_func) { SearchTextContext ctx; - unsigned char *data; + const unsigned char *data; size_t size, max_searchword_len; memset(&ctx, 0, sizeof(ctx)); @@ -545,33 +546,33 @@ mail_search_args_foreach(args, search_func, &ctx); max_searchword_len = ctx.max_searchword_len; - io_buffer_set_read_limit(inbuf, inbuf->offset + max_size); + i_buffer_set_read_limit(inbuf, inbuf->v_offset + max_size); /* do this in blocks: read data, compare it for all search words, skip for block size - (strlen(largest_searchword)-1) and continue. */ - while (io_buffer_read_data_blocking(inbuf, &data, &size, - max_searchword_len-1) > 0) { + while (i_buffer_read_data(inbuf, &data, &size, + max_searchword_len-1) > 0) { ctx.msg = (char *) data; ctx.size = size; mail_search_args_foreach(args, search_func, &ctx); - io_buffer_skip(inbuf, size - (max_searchword_len-1)); + i_buffer_skip(inbuf, size - (max_searchword_len-1)); } if (size > 0) { /* last block */ - ctx.msg = (char *) data; + ctx.msg = (const char *) data; ctx.size = size; mail_search_args_foreach(args, search_func, &ctx); - io_buffer_skip(inbuf, size); + i_buffer_skip(inbuf, size); } - io_buffer_set_read_limit(inbuf, 0); + i_buffer_set_read_limit(inbuf, 0); } static int search_arg_match_text(IndexMailbox *ibox, MailIndexRecord *rec, MailSearchArg *args) { - IOBuffer *inbuf; + IBuffer *inbuf; MessageSize hdr_size; int have_headers, have_body, have_text; @@ -604,10 +605,11 @@ } if (have_text) { - if (inbuf->offset != 0) { + if (inbuf->v_offset != 0) { /* need to rewind back to beginning of headers */ - if (!io_buffer_seek(inbuf, 0)) { - i_error("io_buffer_seek() failed: %m"); + if (!i_buffer_seek(inbuf, 0)) { + errno = inbuf->buf_errno; + i_error("i_buffer_seek() failed: %m"); return FALSE; } } @@ -617,16 +619,16 @@ } if (have_text || have_body) { - if (inbuf->offset == 0) { + if (inbuf->v_offset == 0) { /* skip over headers */ - io_buffer_skip(inbuf, hdr_size.physical_size); + i_buffer_skip(inbuf, hdr_size.physical_size); } search_arg_match_data(inbuf, rec->body_size, args, search_text_body); } - io_buffer_unref(inbuf); + i_buffer_unref(inbuf); return TRUE; } @@ -739,7 +741,7 @@ } static int search_messages(IndexMailbox *ibox, MailSearchArg *args, - IOBuffer *outbuf, int uid_result) + OBuffer *outbuf, int uid_result) { SearchIndexContext ctx; MailIndexRecord *rec; @@ -795,7 +797,7 @@ if (found) { i_snprintf(num, sizeof(num), " %u", uid_result ? rec->uid : client_seq); - io_buffer_send(outbuf, num, strlen(num)); + o_buffer_send(outbuf, num, strlen(num)); } } @@ -806,7 +808,7 @@ } int index_storage_search(Mailbox *box, MailSearchArg *args, - IOBuffer *outbuf, int uid_result) + OBuffer *outbuf, int uid_result) { IndexMailbox *ibox = (IndexMailbox *) box; int failed; @@ -817,9 +819,9 @@ if (!ibox->index->set_lock(ibox->index, MAIL_LOCK_SHARED)) return mail_storage_set_index_error(ibox); - io_buffer_send(outbuf, "* SEARCH", 8); + o_buffer_send(outbuf, "* SEARCH", 8); failed = !search_messages(ibox, args, outbuf, uid_result); - io_buffer_send(outbuf, "\r\n", 2); + o_buffer_send(outbuf, "\r\n", 2); if (!ibox->index->set_lock(ibox->index, MAIL_LOCK_UNLOCK)) return mail_storage_set_index_error(ibox);
--- a/src/lib-storage/index/index-storage.h Sun Oct 13 18:52:19 2002 +0300 +++ b/src/lib-storage/index/index-storage.h Mon Oct 14 02:49:11 2002 +0300 @@ -40,7 +40,7 @@ MailIndexRecord **rec); int index_storage_save_into_fd(MailStorage *storage, int fd, const char *path, - IOBuffer *buf, uoff_t data_size); + IBuffer *buf, uoff_t data_size); void *index_msgcache_get_context(MailIndex *index, MailIndexRecord *rec); @@ -61,8 +61,8 @@ MailFlagUpdateFunc func, void *context, int *all_found); int index_storage_fetch(Mailbox *box, MailFetchData *fetch_data, - IOBuffer *outbuf, int *all_found); + OBuffer *outbuf, int *all_found); int index_storage_search(Mailbox *box, MailSearchArg *args, - IOBuffer *outbuf, int uid_result); + OBuffer *outbuf, int uid_result); #endif
--- a/src/lib-storage/index/maildir/maildir-save.c Sun Oct 13 18:52:19 2002 +0300 +++ b/src/lib-storage/index/maildir/maildir-save.c Mon Oct 14 02:49:11 2002 +0300 @@ -1,8 +1,8 @@ /* Copyright (C) 2002 Timo Sirainen */ #include "lib.h" +#include "ioloop.h" #include "hostpid.h" -#include "iobuffer.h" #include "maildir-index.h" #include "maildir-storage.h" @@ -41,7 +41,7 @@ } static const char *maildir_read_into_tmp(MailStorage *storage, const char *dir, - IOBuffer *buf, uoff_t data_size) + IBuffer *buf, uoff_t data_size) { const char *fname, *path; int fd; @@ -63,7 +63,7 @@ int maildir_storage_save(Mailbox *box, MailFlags flags, const char *custom_flags[], time_t internal_date, - IOBuffer *data, uoff_t data_size) + IBuffer *data, uoff_t data_size) { IndexMailbox *ibox = (IndexMailbox *) box; struct utimbuf buf;
--- a/src/lib-storage/index/maildir/maildir-storage.h Sun Oct 13 18:52:19 2002 +0300 +++ b/src/lib-storage/index/maildir/maildir-storage.h Mon Oct 14 02:49:11 2002 +0300 @@ -7,7 +7,7 @@ const char *messageset, int uidset); int maildir_storage_save(Mailbox *box, MailFlags flags, const char *custom_flags[], time_t internal_date, - IOBuffer *data, uoff_t data_size); + IBuffer *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 Sun Oct 13 18:52:19 2002 +0300 +++ b/src/lib-storage/index/mbox/mbox-expunge.c Mon Oct 14 02:49:11 2002 +0300 @@ -1,7 +1,8 @@ /* Copyright (C) 2002 Timo Sirainen */ #include "lib.h" -#include "iobuffer.h" +#include "ibuffer.h" +#include "obuffer.h" #include "mbox-index.h" #include "mbox-storage.h" #include "mbox-lock.h" @@ -10,14 +11,14 @@ #include <unistd.h> static int expunge_real(IndexMailbox *ibox, MailIndexRecord *rec, - unsigned int seq, IOBuffer *inbuf, IOBuffer *outbuf, + unsigned int seq, IBuffer *inbuf, OBuffer *outbuf, MailExpungeFunc expunge_func, void *context) { - uoff_t offset, end_offset, from_offset, copy_size; + uoff_t offset, end_offset, from_offset, copy_size, old_limit; unsigned int uid; - unsigned char *data; + const unsigned char *data; size_t size; - int expunges; + int expunges, failed; if (seq == 1) end_offset = 0; @@ -34,6 +35,8 @@ rec = ibox->index->next(ibox->index, rec); } + old_limit = inbuf->v_limit; + expunges = FALSE; while (rec != NULL) { if (!mbox_mail_get_start_offset(ibox->index, rec, &offset)) @@ -57,31 +60,34 @@ if (!expunges) { /* first expunged record, seek to position where we want to begin writing */ - if (!io_buffer_seek(outbuf, from_offset)) + if (!o_buffer_seek(outbuf, from_offset)) return FALSE; expunges = TRUE; } } else if (expunges) { /* seek to wanted input position, and copy this messages */ - i_assert(inbuf->offset <= from_offset); - io_buffer_skip(inbuf, from_offset - inbuf->offset); + i_assert(inbuf->v_offset <= from_offset); + i_buffer_skip(inbuf, from_offset - inbuf->v_offset); - if (outbuf->offset == 0) { + if (outbuf->v_offset == 0) { /* we're writing to beginning of mbox, so we don't want the [\r]\n there */ - (void)io_buffer_read_data_blocking(inbuf, &data, - &size, 1); + (void)i_buffer_read_data(inbuf, &data, + &size, 1); if (size > 0 && data[0] == '\n') - io_buffer_skip(inbuf, 1); + i_buffer_skip(inbuf, 1); else if (size > 1 && data[0] == '\r' && data[1] == '\n') - io_buffer_skip(inbuf, 2); + i_buffer_skip(inbuf, 2); } - copy_size = end_offset - inbuf->offset; - if (io_buffer_send_iobuffer(outbuf, inbuf, - copy_size) < 0) + i_buffer_set_read_limit(inbuf, + end_offset - inbuf->v_offset); + failed = o_buffer_send_ibuffer(outbuf, inbuf) < 0; + i_buffer_set_read_limit(inbuf, old_limit); + + if (failed || inbuf->v_offset != end_offset) return FALSE; } @@ -89,23 +95,28 @@ seq++; } - io_buffer_skip(inbuf, end_offset - inbuf->offset); + i_buffer_skip(inbuf, end_offset - inbuf->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->size - inbuf->offset; - if (outbuf->offset == 0 && copy_size == 1) + copy_size = inbuf->v_size - inbuf->v_offset; + if (outbuf->v_offset == 0 && copy_size == 1) return TRUE; - else - return io_buffer_send_iobuffer(outbuf, inbuf, copy_size) > 0; + + i_buffer_set_read_limit(inbuf, copy_size); + failed = o_buffer_send_ibuffer(outbuf, inbuf) < 0; + i_buffer_set_read_limit(inbuf, old_limit); + + return !failed && inbuf->v_offset == end_offset; } int mbox_expunge_locked(IndexMailbox *ibox, MailExpungeFunc expunge_func, void *context) { MailIndexRecord *rec; - IOBuffer *inbuf, *outbuf; + IBuffer *inbuf; + OBuffer *outbuf; unsigned int seq; int failed; @@ -122,25 +133,24 @@ return FALSE; if (!mbox_lock_write(ibox->index)) { - io_buffer_unref(inbuf); + i_buffer_unref(inbuf); return FALSE; } t_push(); - outbuf = io_buffer_create_file(inbuf->fd, data_stack_pool, 4096, FALSE); + outbuf = o_buffer_create_file(ibox->index->mbox_fd, data_stack_pool, + 4096, IO_PRIORITY_DEFAULT, FALSE); failed = !expunge_real(ibox, rec, seq, inbuf, outbuf, expunge_func, context); - if (failed && outbuf->offset > 0) { + if (failed && outbuf->v_offset > 0) { /* we moved some of the data. move the rest as well so there won't be invalid holes in mbox file */ - i_assert(inbuf->offset <= inbuf->size); - (void)io_buffer_send_iobuffer(outbuf, inbuf, - inbuf->size - inbuf->offset); + (void)o_buffer_send_ibuffer(outbuf, inbuf); } - if (ftruncate(outbuf->fd, outbuf->offset) < 0) { + if (ftruncate(ibox->index->mbox_fd, outbuf->v_offset) < 0) { mail_storage_set_error(ibox->box.storage, "ftruncate() failed " "for mbox file %s: %m", ibox->index->mbox_path); @@ -148,7 +158,7 @@ } (void)mbox_unlock(ibox->index); - io_buffer_unref(outbuf); + o_buffer_unref(outbuf); t_pop(); return !failed;
--- a/src/lib-storage/index/mbox/mbox-save.c Sun Oct 13 18:52:19 2002 +0300 +++ b/src/lib-storage/index/mbox/mbox-save.c Mon Oct 14 02:49:11 2002 +0300 @@ -2,7 +2,7 @@ #include "lib.h" #include "hostpid.h" -#include "iobuffer.h" +#include "ibuffer.h" #include "write-full.h" #include "mbox-index.h" #include "mbox-lock.h" @@ -145,12 +145,12 @@ } int mbox_storage_save(Mailbox *box, MailFlags flags, const char *custom_flags[], - time_t internal_date, IOBuffer *data, uoff_t data_size) + time_t internal_date, IBuffer *data, uoff_t data_size) { IndexMailbox *ibox = (IndexMailbox *) box; MailFlags real_flags; const char *mbox_path; - IOBuffer *inbuf; + IBuffer *inbuf; int fd, failed; off_t pos; @@ -165,12 +165,12 @@ if (!index_mailbox_fix_custom_flags(ibox, &real_flags, custom_flags)) return FALSE; - /* just make sure the mbox is opened, we don't need the iobuffer */ + /* just make sure the mbox is opened, we don't need the ibuffer */ inbuf = mbox_file_open(ibox->index, 0, TRUE); if (inbuf == NULL) return FALSE; - io_buffer_unref(inbuf); + i_buffer_unref(inbuf); fd = ibox->index->mbox_fd; if (!mbox_lock_write(ibox->index)) {
--- a/src/lib-storage/index/mbox/mbox-storage.h Sun Oct 13 18:52:19 2002 +0300 +++ b/src/lib-storage/index/mbox/mbox-storage.h Mon Oct 14 02:49:11 2002 +0300 @@ -6,7 +6,7 @@ int mbox_storage_copy(Mailbox *box, Mailbox *destbox, const char *messageset, int uidset); int mbox_storage_save(Mailbox *box, MailFlags flags, const char *custom_flags[], - time_t internal_date, IOBuffer *data, uoff_t data_size); + time_t internal_date, IBuffer *data, uoff_t data_size); int mbox_find_mailboxes(MailStorage *storage, const char *mask, MailboxFunc func, void *context);
--- a/src/lib-storage/mail-storage.h Sun Oct 13 18:52:19 2002 +0300 +++ b/src/lib-storage/mail-storage.h Mon Oct 14 02:49:11 2002 +0300 @@ -159,16 +159,16 @@ /* Fetch wanted mail data. The results are written into outbuf in RFC2060 FETCH format. */ int (*fetch)(Mailbox *box, MailFetchData *fetch_data, - IOBuffer *outbuf, int *all_found); + OBuffer *outbuf, int *all_found); /* Search wanted mail data. args contains the search criteria. results are written into outbuf in RFC2060 SEARCH format. */ int (*search)(Mailbox *box, MailSearchArg *args, - IOBuffer *outbuf, int uid_result); + OBuffer *outbuf, int uid_result); /* Save a new mail into mailbox. */ int (*save)(Mailbox *box, MailFlags flags, const char *custom_flags[], - time_t internal_date, IOBuffer *data, uoff_t data_size); + time_t internal_date, IBuffer *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 Sun Oct 13 18:52:19 2002 +0300 +++ b/src/lib/Makefile.am Mon Oct 14 02:49:11 2002 +0300 @@ -24,6 +24,10 @@ hostpid.c \ imem.c \ iobuffer.c \ + ibuffer.c \ + ibuffer-data.c \ + ibuffer-file.c \ + ibuffer-mmap.c \ ioloop.c \ $(ioloop_source) \ lib.c \ @@ -36,6 +40,8 @@ mmap-anon.c \ mmap-util.c \ network.c \ + obuffer.c \ + obuffer-file.c \ primes.c \ randgen.c \ restrict-access.c \ @@ -59,7 +65,9 @@ hex-binary.h \ hostpid.h \ imem.h \ - iobuffer.h \ + iobuffer-internal.h \ + ibuffer.h \ + ibuffer-internal.h \ ioloop.h \ ioloop-internal.h \ lib.h \ @@ -69,6 +77,8 @@ mempool.h \ mmap-util.h \ network.h \ + obuffer.h \ + obuffer-internal.h \ primes.h \ randgen.h \ restrict-access.h \
--- a/src/lib/compat.c Sun Oct 13 18:52:19 2002 +0300 +++ b/src/lib/compat.c Mon Oct 14 02:49:11 2002 +0300 @@ -134,3 +134,29 @@ #endif } #endif + +#ifndef HAVE_WRITEV +ssize_t my_writev(int fd, const struct iovec *iov, size_t iov_len) +{ + size_t i, written; + ssize_t ret; + + written = 0; + for (i = 0; i < iov_len; i++, iov++) { + ret = write(fd, iov->iov_base, iov->iov_len); + if (ret < 0) + return -1; + + written += ret; + if ((size_t)ret != iov->iov_len) + break; + } + + if (written > SSIZE_T_MAX) { + errno = ERANGE; + return -1; + } + + return (ssize_t)written; +} +#endif
--- a/src/lib/compat.h Sun Oct 13 18:52:19 2002 +0300 +++ b/src/lib/compat.h Mon Oct 14 02:49:11 2002 +0300 @@ -62,6 +62,19 @@ int my_getpagesize(void); #endif +#ifndef HAVE_STRUCT_IOVEC +struct iovec { + void *iov_base; + size_t iov_len; +}; +#endif + +#ifndef HAVE_WRITEV +# define writev my_writev +struct iovec; +ssize_t my_writev(int fd, const struct iovec *iov, size_t iov_len); +#endif + /* ctype.h isn't safe with signed chars, use our own instead if really needed */ #define i_toupper(x) ((char) toupper((int) (unsigned char) (x)))
--- a/src/lib/data-stack.c Sun Oct 13 18:52:19 2002 +0300 +++ b/src/lib/data-stack.c Mon Oct 14 02:49:11 2002 +0300 @@ -365,6 +365,8 @@ StackFrame *frame; frame = malloc(sizeof(StackFrame)); + if (frame == NULL) + i_panic("t_push(): Out of memory"); frame->allocs = NULL; frame->next = current_frame; @@ -397,6 +399,8 @@ FrameAlloc *alloc; alloc = malloc(sizeof(FrameAlloc)); + if (alloc == NULL) + i_panic("add_alloc(): Out of memory"); alloc->mem = mem; alloc->next = current_frame->allocs; current_frame->allocs = alloc; @@ -412,6 +416,8 @@ void *mem; mem = malloc(size); + if (mem == NULL) + i_panic("t_malloc(): Out of memory"); add_alloc(mem); return mem; } @@ -421,6 +427,8 @@ void *mem; mem = calloc(size, 1); + if (mem == NULL) + i_panic("t_malloc0(): Out of memory"); add_alloc(mem); return mem; } @@ -440,6 +448,8 @@ void *t_buffer_get(size_t size) { buffer_mem = realloc(buffer_mem, size); + if (buffer_mem == NULL) + i_panic("t_buffer_get(): Out of memory"); return buffer_mem; } @@ -448,6 +458,8 @@ i_assert(buffer == buffer_mem); buffer_mem = realloc(buffer_mem, size); + if (buffer_mem == NULL) + i_panic("t_buffer_reget(): Out of memory"); return buffer_mem; } @@ -458,6 +470,8 @@ i_assert(buffer_mem != NULL); mem = realloc(buffer_mem, size); + if (mem == NULL) + i_panic("t_buffer_alloc(): Out of memory"); buffer_mem = NULL; add_alloc(mem);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/lib/ibuffer-data.c Mon Oct 14 02:49:11 2002 +0300 @@ -0,0 +1,84 @@ +/* + 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__, + TimeoutFunc timeout_func __attr_unused__, + void *context __attr_unused__) +{ +} + +static ssize_t _read(_IBuffer *buf) +{ + return buf->pos - buf->skip; +} + +static int _seek(_IBuffer *buf, uoff_t v_offset) +{ + buf->skip = v_offset; + return 1; +} + +static int _skip(_IBuffer *buf, uoff_t count) +{ + buf->skip += count; + return 1; +} + +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->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); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/lib/ibuffer-file.c Mon Oct 14 02:49:11 2002 +0300 @@ -0,0 +1,305 @@ +/* + 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 "ibuffer-internal.h" + +#include <unistd.h> + +#define I_BUFFER_MIN_SIZE 1024 + +typedef struct { + _IBuffer ibuf; + + size_t max_buffer_size; + + int timeout_msecs; + TimeoutFunc timeout_func; + void *timeout_context; + + unsigned int autoclose_fd:1; +} FileIBuffer; + +typedef struct { + IOLoop ioloop; + IBuffer *buf; + int timeout; +} IOLoopReadContext; + +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, + TimeoutFunc timeout_func, void *context) +{ + FileIBuffer *fbuf = (FileIBuffer *) buf; + + fbuf->timeout_msecs = timeout_msecs; + fbuf->timeout_func = timeout_func; + fbuf->timeout_context = context; +} + +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 void ioloop_read(void *context, int fd __attr_unused__, + IO io __attr_unused__) +{ + IOLoopReadContext *ctx = context; + + if (i_buffer_read(ctx->buf) != 0) { + /* got data / error */ + io_loop_stop(ctx->ioloop); + } +} + +static void ioloop_timeout(void *context, Timeout timeout __attr_unused__) +{ + IOLoopReadContext *ctx = context; + + ctx->timeout = TRUE; + io_loop_stop(ctx->ioloop); +} + +static ssize_t i_buffer_read_blocking(_IBuffer *buf) +{ + FileIBuffer *fbuf = (FileIBuffer *) buf; + IOLoopReadContext ctx; + Timeout to; + IO io; + + t_push(); + + /* create a new I/O loop */ + memset(&ctx, 0, sizeof(ctx)); + ctx.ioloop = io_loop_create(data_stack_pool); + ctx.buf = &buf->ibuffer; + + io = io_add(buf->fd, IO_READ, ioloop_read, &ctx); + to = fbuf->timeout_msecs <= 0 ? NULL : + timeout_add(fbuf->timeout_msecs, ioloop_timeout, &ctx); + + io_loop_run(ctx.ioloop); + + io_remove(io); + if (to != NULL) { + if (ctx.timeout && fbuf->timeout_func != NULL) { + /* call user-given timeout function */ + fbuf->timeout_func(fbuf->timeout_context, to); + } + timeout_remove(to); + } + + io_loop_destroy(ctx.ioloop); + t_pop(); + + return buf->pos > buf->skip ? (ssize_t) (buf->pos-buf->skip) : -1; +} + +static ssize_t _read(_IBuffer *buf) +{ + FileIBuffer *fbuf = (FileIBuffer *) buf; + size_t size; + ssize_t ret; + + 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); + if (size >= buf->ibuffer.v_limit - buf->ibuffer.v_offset) { + size = buf->ibuffer.v_limit - buf->ibuffer.v_offset; + if (size == 0) { + /* virtual limit reached == EOF */ + return -1; + } + } + } + + ret = read(buf->fd, buf->w_buffer + buf->pos, size); + if (ret == 0) { + /* EOF */ + return -1; + } + + if (ret < 0) { + if (errno == EINTR || errno == EAGAIN) + ret = 0; + else { + buf->ibuffer.buf_errno = errno; + return -1; + } + } + + if (ret > 0 || fbuf->timeout_msecs == 0) { + buf->pos += ret; + return ret; + } else { + /* blocking read */ + return i_buffer_read_blocking(buf); + } +} + +static int _skip(_IBuffer *buf, uoff_t count) +{ + uoff_t old_limit; + ssize_t ret; + off_t skipped; + + if (buf->buffer_size == 0) + i_buffer_grow(buf, I_BUFFER_MIN_SIZE); + + skipped = 0; + old_limit = buf->ibuffer.v_limit; + i_buffer_set_read_limit(&buf->ibuffer, buf->ibuffer.v_offset + count); + + while (count > 0 && (ret = i_buffer_read(&buf->ibuffer)) > 0) { + if ((size_t)ret > count) + ret = count; + + count -= ret; + buf->skip += ret; + buf->ibuffer.v_offset += ret; + } + + i_buffer_set_read_limit(&buf->ibuffer, old_limit); + return count > 0 ? -1 : 1; +} + +static int _seek(_IBuffer *buf, uoff_t v_offset) +{ + 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 = EINVAL; + return -1; + } + + ret = lseek(buf->fd, (off_t)real_offset, SEEK_SET); + if (ret < 0) { + buf->ibuffer.buf_errno = errno; + return -1; + } + + if (ret != (off_t)real_offset) { + buf->ibuffer.buf_errno = EINVAL; + return -1; + } + + buf->ibuffer.buf_errno = 0; + buf->ibuffer.v_offset = v_offset; + return 1; +} + +IBuffer *i_buffer_create_file(int fd, Pool pool, size_t max_buffer_size, + int autoclose_fd) +{ + FileIBuffer *mbuf; + + mbuf = p_new(pool, FileIBuffer, 1); + mbuf->max_buffer_size = max_buffer_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, 0, 0); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/lib/ibuffer-internal.h Mon Oct 14 02:49:11 2002 +0300 @@ -0,0 +1,33 @@ +#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); + int (*skip_count)(_IBuffer *buf, uoff_t count); + int (*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; + int last_cr; +}; + +IBuffer *_i_buffer_create(_IBuffer *_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/ibuffer-mmap.c Mon Oct 14 02:49:11 2002 +0300 @@ -0,0 +1,235 @@ +/* + 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; + uoff_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__, + TimeoutFunc timeout_func __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 */ + 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; + + (void)madvise(mbuf->mmap_base, limit_size, MADV_SEQUENTIAL); + } + + return io_buffer_set_mmaped_pos(buf); +} + +static int _seek(_IBuffer *buf, uoff_t v_offset) +{ + MmapIBuffer *mbuf = (MmapIBuffer *) buf; + uoff_t abs_offset; + + abs_offset = buf->ibuffer.start_offset + v_offset; + if (mbuf->mmap_offset >= abs_offset && + mbuf->mmap_offset + buf->pos < abs_offset) { + /* already mmaped */ + buf->skip = mbuf->mmap_offset - abs_offset; + buf->pos = buf->buffer_size; + } else { + /* force reading next time */ + i_buffer_munmap(mbuf); + buf->skip = buf->pos = 0; + } + + return 1; +} + +static int _skip(_IBuffer *buf, uoff_t count) +{ + return _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; + } + } + + 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); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/lib/ibuffer.c Mon Oct 14 02:49:11 2002 +0300 @@ -0,0 +1,250 @@ +/* + 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, + TimeoutFunc timeout_func, 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; + _buf->last_cr = FALSE; +} + +void i_buffer_set_read_limit(IBuffer *buf, uoff_t v_offset) +{ + _IBuffer *_buf = buf->real_buffer; + + i_assert(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); +} + +int 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 1; + } + + if (buf->closed) + return -1; + + data_size = _buf->pos - _buf->skip; + _buf->skip = _buf->pos = 0; + + count -= data_size; + buf->v_offset += data_size; + + return _buf->skip_count(_buf, count); +} + +int 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 -1; + + return _buf->seek(_buf, v_offset); +} + +/* skip the first LF, if it exists */ +static void i_buffer_skip_lf(_IBuffer *_buf) +{ + if (!_buf->last_cr || _buf->skip >= _buf->pos) + return; + + if (_buf->buffer[_buf->skip] == 10) { + if (_buf->skip == _buf->cr_lookup_pos) + _buf->cr_lookup_pos++; + _buf->skip++; + _buf->ibuffer.v_offset++; + } + _buf->last_cr = FALSE; +} + +char *i_buffer_next_line(IBuffer *buf) +{ + _IBuffer *_buf = buf->real_buffer; + char *ret_buf; + size_t i; + + i_assert(buf != NULL); + + i_buffer_skip_lf(_buf); + 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] == 13 || _buf->buffer[i] == 10) { + /* got it */ + _buf->last_cr = _buf->buffer[i] == 13; + + ret_buf = (char *) _buf->buffer + _buf->skip; + _buf->w_buffer[i] = '\0'; + + 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; + + i_buffer_skip_lf(_buf); + + if (_buf->skip >= _buf->pos) { + *size = 0; + return NULL; + } + + *size = _buf->pos - _buf->skip; + return _buf->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; + + while (_buf->pos - _buf->skip <= threshold) { + /* we need more data */ + ret = _buf->read(_buf); + if (ret < 0) { + if (ret == -2) + return -2; + else + break; + } + } + + *data = i_buffer_get_data(buf, size); + return *size > threshold ? 1 : *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; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/lib/ibuffer.h Mon Oct 14 02:49:11 2002 +0300 @@ -0,0 +1,73 @@ +#ifndef __IBUFFER_H +#define __IBUFFER_H + +#include "ioloop.h" /* TimeoutFunc */ + +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. The blocking state in file + descriptor isn't changed, but for timeout to work it must be in + non-blocking state. Setting timeout_msecs to 0 makes it non-blocking. */ +void i_buffer_set_blocking(IBuffer *buf, int timeout_msecs, + TimeoutFunc timeout_func, 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. Returns 1 if all bytes were actually + skipped, or -1 if EOF or error. */ +int i_buffer_skip(IBuffer *buf, uoff_t count); +/* Seek to specified position from beginning of file. This works only for + files. Returns 1 if successful, -1 if error. */ +int 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 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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/lib/iobuffer-internal.h Mon Oct 14 02:49:11 2002 +0300 @@ -0,0 +1,29 @@ +#ifndef __IOBUFFER_INTERNAL_H +#define __IOBUFFER_INTERNAL_H + +#include "ioloop.h" /* TimeoutFunc */ + +/* 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, + TimeoutFunc timeout_func, 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, + TimeoutFunc timeout_func, void *context); + +#endif
--- a/src/lib/iobuffer.c Sun Oct 13 18:52:19 2002 +0300 +++ b/src/lib/iobuffer.c Mon Oct 14 02:49:11 2002 +0300 @@ -1,5 +1,5 @@ /* - iobuffer.c : Input/output transmit buffer handling + iobuffer.c : Input/output buffer common handling Copyright (c) 2002 Timo Sirainen @@ -24,1158 +24,47 @@ */ #include "lib.h" -#include "ioloop.h" -#include "iobuffer.h" -#include "mmap-util.h" -#include "sendfile-util.h" -#include "network.h" - -#include <unistd.h> -#include <sys/stat.h> - -#define IO_BUFFER_MIN_SIZE 4096 - -#define MAX_SSIZE_T(size) ((size) < SSIZE_T_MAX ? (size_t)(size) : SSIZE_T_MAX) - -typedef struct { - IOLoop ioloop; - IOBuffer *outbuf; - - const char *data; - uoff_t size; - IOBuffer *inbuf; +#include "iobuffer-internal.h" - int timeout; - int last_block; -} IOBufferBlockContext; - -static size_t mmap_pagesize = 0; -static size_t mmap_pagemask = 0; - -IOBuffer *io_buffer_create(int fd, Pool pool, int priority, - size_t max_buffer_size) +void _io_buffer_init(Pool pool, _IOBuffer *buf) { - IOBuffer *buf; - - i_assert(fd >= 0); - i_assert(pool != NULL); - - pool_ref(pool); - buf = p_new(pool, IOBuffer, 1); + buf->pool = pool; buf->refcount = 1; - buf->fd = fd; - buf->pool = pool; - buf->priority = priority; - buf->max_buffer_size = max_buffer_size; - return buf; } -IOBuffer *io_buffer_create_file(int fd, Pool pool, size_t max_buffer_size, - int flags) -{ - IOBuffer *buf; - - buf = io_buffer_create(fd, pool, IO_PRIORITY_DEFAULT, max_buffer_size); - buf->file = TRUE; - buf->close_file = (flags & IOBUFFER_FLAG_AUTOCLOSE) != 0; - return buf; -} - -IOBuffer *io_buffer_create_mmap(int fd, Pool pool, size_t block_size, - uoff_t start_offset, uoff_t size, int flags) -{ - IOBuffer *buf; - struct stat st; - uoff_t stop_offset; - - i_assert(start_offset < OFF_T_MAX); - - /* block size must be page aligned, and at least two pages long */ - if (mmap_pagesize == 0) { - mmap_pagesize = getpagesize(); - mmap_pagemask = mmap_pagesize-1; - } - - if (block_size < mmap_pagesize*2) - block_size = mmap_pagesize*2; - else if ((block_size & mmap_pagemask) != 0) { - block_size &= ~mmap_pagemask; - block_size += mmap_pagesize; - } - - buf = io_buffer_create_file(fd, pool, block_size, flags); - buf->mmaped = TRUE; - buf->receive = TRUE; - - if (fstat(fd, &st) == 0) - stop_offset = (uoff_t)st.st_size; - else { - i_error("io_buffer_create_mmap(): lseek() failed: %m"); - stop_offset = 0; - } - - if (start_offset > stop_offset) - start_offset = stop_offset; - - if (size > stop_offset-start_offset) { - i_warning("Trying to create IOBuffer with size " - "%"PRIuUOFF_T" but we have only %"PRIuUOFF_T - " bytes available in file", size, - stop_offset-start_offset); - size = stop_offset-start_offset; - } - - if (size == 0) - size = stop_offset - start_offset; - - buf->start_offset = start_offset; - buf->limit = buf->size = size; - - buf->skip = buf->pos = buf->start_offset; - return buf; -} - -void io_buffer_ref(IOBuffer *buf) +void _io_buffer_ref(_IOBuffer *buf) { buf->refcount++; } -void io_buffer_unref(IOBuffer *buf) +void _io_buffer_unref(_IOBuffer *buf) { - if (buf == NULL) - return; + Pool pool; i_assert(buf->refcount > 0); - if (--buf->refcount > 0) - return; - - if (buf->io != NULL) - io_remove(buf->io); - if (buf->buffer != NULL) { - if (!buf->mmaped) - p_free(buf->pool, buf->buffer); - else { - if (munmap(buf->buffer, buf->buffer_size) < 0) { - i_error("io_buffer_destroy(): " - "munmap() failed: %m"); - } - } - } - io_buffer_close(buf); - p_free(buf->pool, buf); - pool_unref(buf->pool); -} - -void io_buffer_close(IOBuffer *buf) -{ - if (buf == NULL) - return; - - buf->closed = TRUE; - if (buf->close_file && buf->fd != -1) { - if (close(buf->fd) < 0) - i_error("io_buffer_close(): close() failed: %m"); - buf->fd = -1; - } -} - -void io_buffer_reset(IOBuffer *buf) -{ - buf->pos = buf->skip = buf->cr_lookup_pos = 0; - buf->last_cr = FALSE; - - if (buf->mmaped && buf->buffer != NULL) { - if (munmap(buf->buffer, buf->buffer_size) < 0) - i_error("io_buffer_reset(): munmap() failed: %m"); - buf->buffer = NULL; - buf->buffer_size = 0; - } - - buf->mmap_offset = buf->offset = 0; -} - -IOBuffer *io_buffer_set_pool(IOBuffer *buf, Pool pool) -{ - IOBuffer *newbuf; - - i_assert(buf != NULL); - i_assert(pool != NULL); - - newbuf = p_new(pool, IOBuffer, 1); - memcpy(newbuf, buf, sizeof(IOBuffer)); - - newbuf->pool = pool; - - if (!newbuf->mmaped) { - newbuf->buffer = p_malloc(pool, buf->buffer_size); - memcpy(newbuf->buffer, buf->buffer + buf->skip, - buf->buffer_size - buf->skip); - - newbuf->cr_lookup_pos -= newbuf->skip; - newbuf->pos -= newbuf->skip; - newbuf->skip = 0; - - p_free(buf->pool, buf->buffer); - } - - p_free(buf->pool, buf); - return newbuf; -} - -void io_buffer_set_max_size(IOBuffer *buf, size_t max_size) -{ - i_assert(!buf->mmaped); - - buf->max_buffer_size = max_size; -} - -void io_buffer_set_blocking(IOBuffer *buf, size_t max_size, - int timeout_msecs, TimeoutFunc timeout_func, - void *context) -{ - buf->timeout_msecs = timeout_msecs; - buf->timeout_func = timeout_func; - buf->timeout_context = context; - buf->blocking = max_size > 0; - - if (max_size != 0) - buf->max_buffer_size = max_size; -} - -static ssize_t my_write(int fd, const void *buf, size_t size) -{ - ssize_t ret; - - ret = write(fd, buf, size); - if (ret < 0 && (errno == EINTR || errno == EAGAIN)) - ret = 0; - - return ret; -} - -static ssize_t io_buffer_write(IOBuffer *buf, const void *data, size_t size) -{ - ssize_t ret; - - if (size > SSIZE_T_MAX) - size = SSIZE_T_MAX; - if (size == 0) - return 0; - - ret = buf->file ? my_write(buf->fd, data, size) : - net_transmit(buf->fd, data, size); - if (ret < 0) { - /* disconnected */ - buf->buf_errno = errno; - io_buffer_close(buf); - return -1; - } - - buf->offset += ret; - return ret; -} - -static void buf_send_real(IOBuffer *buf) -{ - ssize_t ret; - - ret = io_buffer_write(buf, buf->buffer + buf->skip, - buf->pos - buf->skip); - if (ret < 0) + if (--buf->refcount != 0) return; - buf->skip += ret; - if (buf->skip == buf->pos) { - /* everything sent */ - buf->skip = buf->pos = 0; - - /* call flush function */ - if (buf->flush_func != NULL) { - buf->flush_func(buf->flush_context, buf); - buf->flush_func = NULL; - - if (buf->corked) { - /* remove cork */ - if (!buf->file) - net_set_cork(buf->fd, FALSE); - buf->corked = FALSE; - } - } - } -} - -static int buf_send(IOBuffer *buf) -{ - buf_send_real(buf); - - if (buf->closed || buf->pos == 0) { - io_remove(buf->io); - buf->io = NULL; - return FALSE; - } - - return TRUE; -} - -#define IOBUFFER_IS_FULL(buf) \ - ((buf)->pos == (buf)->buffer_size) - -/* write only as much as needed, put the rest into buffer. - write() only full buffers. */ -static void block_loop_send(IOBufferBlockContext *ctx) -{ - size_t size, buffer_space_left; - ssize_t ret; - - size = MAX_SSIZE_T(ctx->size); - - buffer_space_left = ctx->outbuf->buffer_size - ctx->outbuf->pos; - if (ctx->outbuf->pos != 0 || ctx->size < buffer_space_left) { - if (buffer_space_left > 0) { - /* we have space in the buffer, fill it before - writing */ - if (size > buffer_space_left) - size = buffer_space_left; - - memcpy(ctx->outbuf->buffer + ctx->outbuf->pos, - ctx->data, size); - ctx->outbuf->pos += size; - - ctx->data += size; - ctx->size -= size; - } - - if (IOBUFFER_IS_FULL(ctx->outbuf)) - buf_send_real(ctx->outbuf); - } else { - ret = io_buffer_write(ctx->outbuf, ctx->data, size); - if (ret > 0) { - ctx->data += ret; - ctx->size -= ret; - } - } - - if (ctx->outbuf->closed || (ctx->size == 0 && ctx->last_block && - !IOBUFFER_IS_FULL(ctx->outbuf))) - io_loop_stop(ctx->ioloop); -} - -/* write out all data from buffer */ -static void block_loop_flush(IOBufferBlockContext *ctx) -{ - if (ctx->outbuf->skip != ctx->outbuf->pos) - buf_send_real(ctx->outbuf); - - if (ctx->outbuf->closed || ctx->outbuf->skip == ctx->outbuf->pos) - io_loop_stop(ctx->ioloop); -} - -/* this can be called with both io_buffer_ioloop() or - io_buffer_read_blocking() */ -static void block_loop_timeout(void *context, Timeout timeout __attr_unused__) -{ - IOBufferBlockContext *ctx = context; - - ctx->timeout = TRUE; - io_loop_stop(ctx->ioloop); -} - -static int io_buffer_ioloop(IOBuffer *buf, IOBufferBlockContext *ctx, - void (*send_func)(IOBufferBlockContext *ctx)) -{ - Timeout to; - int save_errno; - - /* close old IO */ - if (buf->io != NULL) - io_remove(buf->io); - - t_push(); - - /* create a new I/O loop */ - ctx->ioloop = io_loop_create(data_stack_pool); - ctx->outbuf = buf; - - buf->io = io_add(buf->fd, IO_WRITE, (IOFunc) send_func, ctx); - to = buf->timeout_msecs <= 0 ? NULL : - timeout_add(buf->timeout_msecs, block_loop_timeout, ctx); - - io_loop_run(ctx->ioloop); - save_errno = errno; - - if (buf->io != NULL) { - io_remove(buf->io); - buf->io = NULL; - } - - if (to != NULL) { - if (ctx->timeout && buf->timeout_func != NULL) { - /* call user-given timeout function */ - buf->timeout_func(buf->timeout_context, to); - } - timeout_remove(to); - } - - io_loop_destroy(ctx->ioloop); - - t_pop(); - - errno = save_errno; - return ctx->size > 0 ? -1 : 1; -} - -static int io_buffer_send_blocking(IOBuffer *buf, const void *data, - size_t size) -{ - IOBufferBlockContext ctx; - - memset(&ctx, 0, sizeof(ctx)); - - ctx.data = data; - ctx.size = size; - ctx.last_block = TRUE; - - return io_buffer_ioloop(buf, &ctx, block_loop_send); -} - -static int io_buffer_flush(IOBuffer *buf) -{ - IOBufferBlockContext ctx; - ssize_t ret; - - if (buf->skip == buf->pos) - return 1; - - ret = io_buffer_write(buf, buf->buffer + buf->skip, - buf->pos - buf->skip); - if (ret < 0) - return -1; - - buf->skip += ret; - if (buf->skip == buf->pos) - return 1; - - memset(&ctx, 0, sizeof(ctx)); - ctx.last_block = TRUE; + buf->close(buf); + buf->destroy(buf); - return io_buffer_ioloop(buf, &ctx, block_loop_flush); -} - -void io_buffer_cork(IOBuffer *buf) -{ - i_assert(!buf->receive); - - if (!buf->corked) { - if (!buf->file) - net_set_cork(buf->fd, TRUE); - buf->corked = TRUE; - } -} - -static void buffer_alloc_more(IOBuffer *buf, size_t size) -{ - i_assert(!buf->mmaped); - - buf->buffer_size = buf->pos+size; - buf->buffer_size = - buf->buffer_size <= IO_BUFFER_MIN_SIZE ? IO_BUFFER_MIN_SIZE : - nearest_power(buf->buffer_size); - - if (buf->max_buffer_size > 0 && buf->buffer_size > buf->max_buffer_size) - buf->buffer_size = buf->max_buffer_size; - - buf->buffer = p_realloc(buf->pool, buf->buffer, buf->buffer_size); - if (buf->buffer == NULL) { - /* pool limit exceeded */ - buf->pos = buf->buffer_size = 0; - } -} - -static void io_buffer_compress(IOBuffer *buf) -{ - memmove(buf->buffer, buf->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; -} - -int io_buffer_send(IOBuffer *buf, const void *data, size_t size) -{ - ssize_t ret; - int i, corked; - - i_assert(!buf->receive); - i_assert(data != NULL); - i_assert(size <= SSIZE_T_MAX); - buf->transmit = TRUE; - - if (buf->closed) - return -1; - - /* if we're corked, first try adding it to buffer. if it's larger - than the buffer, send it immediately. */ - corked = buf->corked; - for (i = 0; i < 2; i++) { - if (buf->pos == 0 && !corked) { - /* buffer is empty, try to send the data immediately */ - ret = io_buffer_write(buf, data, size); - if (ret < 0) - return -1; - - data = (const char *) data + ret; - size -= ret; - } - - if (size == 0) { - /* all sent */ - return 1; - } - - if (io_buffer_get_space(buf, size) != NULL) - break; - - if (corked) - corked = FALSE; - else { - if (buf->blocking) { - /* if we don't have space, we block */ - return io_buffer_send_blocking(buf, data, size); - } - return -2; - } - } - - i_assert(buf->pos + size <= buf->buffer_size); - - /* add to buffer */ - memcpy(buf->buffer + buf->pos, data, size); - buf->pos += size; - - if (buf->io == NULL && !buf->corked) { - buf->io = io_add_priority(buf->fd, buf->priority, IO_WRITE, - (IOFunc) buf_send, buf); - } - return 1; -} - -static void block_loop_sendfile(IOBufferBlockContext *ctx) -{ - uoff_t offset; - ssize_t ret; - - i_assert(ctx->inbuf->offset < OFF_T_MAX); - - offset = ctx->inbuf->offset; - ret = safe_sendfile(ctx->outbuf->fd, ctx->inbuf->fd, &offset, - MAX_SSIZE_T(ctx->size)); - if (ret < 0) { - if (errno != EINTR && errno != EAGAIN) { - ctx->outbuf->buf_errno = errno; - io_buffer_close(ctx->outbuf); - } - ret = 0; - } - - io_buffer_skip(ctx->inbuf, (size_t)ret); - ctx->outbuf->offset += ret; - - ctx->size -= ret; - if (ctx->outbuf->closed || ctx->size == 0) - io_loop_stop(ctx->ioloop); -} - -static int io_buffer_sendfile(IOBuffer *outbuf, IOBuffer *inbuf, - uoff_t long_size) -{ - IOBufferBlockContext ctx; - uoff_t offset; - ssize_t ret; - - i_assert(inbuf->offset < OFF_T_MAX); - - /* flush out any data in buffer */ - if (io_buffer_flush(outbuf) < 0) - return -1; - - /* first try if we can do it with a single sendfile() call */ - offset = inbuf->offset; - ret = safe_sendfile(outbuf->fd, inbuf->fd, &offset, - MAX_SSIZE_T(long_size)); - if (ret < 0) { - if (errno != EINTR && errno != EAGAIN) { - outbuf->buf_errno = errno; - return -1; - } - ret = 0; - } - - io_buffer_skip(inbuf, (size_t)ret); - outbuf->offset += ret; - - if ((uoff_t) ret == long_size) { - /* yes, all sent */ - return 1; - } - - memset(&ctx, 0, sizeof(ctx)); - - ctx.inbuf = inbuf; - ctx.size = long_size - ret; - - ret = io_buffer_ioloop(outbuf, &ctx, block_loop_sendfile); - if (ret < 0 && outbuf->buf_errno == EINVAL) { - /* this shouldn't happen, must be a bug. It would also - mess up later if we let this pass. */ - i_panic("io_buffer_sendfile() failed: %m"); - } - return ret; + pool = buf->pool; + p_free(pool, buf); + pool_unref(pool); } -static void block_loop_copy(IOBufferBlockContext *ctx) -{ - unsigned char *in_data; - size_t size, full_size, sent_size, data_size; - - if (io_buffer_read_data_blocking(ctx->inbuf, &in_data, &size, 0) < 0) { - io_loop_stop(ctx->ioloop); - return; - } - - full_size = ctx->size; - data_size = size < full_size ? size : full_size; - - /* send the data */ - ctx->size = data_size; - ctx->data = (const char *) in_data; - ctx->last_block = data_size == full_size; - block_loop_send(ctx); - - /* ctx->size now contains number of bytes unsent */ - sent_size = data_size - ctx->size; - ctx->size = full_size - sent_size; - - io_buffer_skip(ctx->inbuf, sent_size); -} - -int io_buffer_send_iobuffer(IOBuffer *outbuf, IOBuffer *inbuf, uoff_t size) -{ - IOBufferBlockContext ctx; - int ret; - - i_assert(size < OFF_T_MAX); - i_assert(inbuf->limit > 0 || size <= inbuf->limit - inbuf->offset); - - if (inbuf->closed || outbuf->closed) - return -1; - - ret = io_buffer_sendfile(outbuf, inbuf, size); - if (ret > 0 || outbuf->buf_errno != EINVAL) - return ret < 0 ? -1 : 1; - - /* sendfile() not supported (with this fd), fallback to - regular sending */ - - /* create blocking send loop */ - memset(&ctx, 0, sizeof(ctx)); - - ctx.inbuf = inbuf; - ctx.size = size; - - return io_buffer_ioloop(outbuf, &ctx, block_loop_copy); -} - -void io_buffer_send_flush(IOBuffer *buf) -{ - i_assert(!buf->receive); - - if (buf->closed) - return; - - io_buffer_flush(buf); - - if (buf->corked) { - /* remove cork */ - if (!buf->file) - net_set_cork(buf->fd, FALSE); - buf->corked = FALSE; - } -} - -void io_buffer_send_flush_callback(IOBuffer *buf, IOBufferFlushFunc func, - void *context) -{ - i_assert(!buf->receive); - - if (buf->skip == buf->pos) { - func(context, buf); - return; - } - - buf->flush_func = func; - buf->flush_context = context; - - /* if we're corked, the io wasn't set */ - if (buf->io == NULL) { - buf->io = io_add_priority(buf->fd, buf->priority, IO_WRITE, - (IOFunc) buf_send, buf); - } -} - -static ssize_t io_buffer_set_mmaped_pos(IOBuffer *buf) -{ - i_assert((uoff_t)buf->mmap_offset <= buf->start_offset + buf->limit); - - buf->pos = buf->start_offset + buf->limit - buf->mmap_offset; - if (buf->pos > buf->buffer_size) - buf->pos = buf->buffer_size; - - return buf->pos - buf->skip; -} - -static ssize_t io_buffer_read_mmaped(IOBuffer *buf) +void _io_buffer_close(_IOBuffer *buf) { - size_t aligned_skip; - - if (buf->start_offset + buf->limit <= - (uoff_t)buf->mmap_offset + buf->pos) { - /* end of file */ - 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 && buf->buffer != NULL) { - /* didn't skip enough bytes */ - return -2; - } - - buf->skip -= aligned_skip; - buf->mmap_offset += aligned_skip; - - if (buf->buffer != NULL) { - if (munmap(buf->buffer, buf->buffer_size) < 0) - i_error("io_buffer_read_mmaped(): munmap() failed: %m"); - } - - buf->buffer_size = buf->start_offset + buf->size - buf->mmap_offset; - if (buf->buffer_size > buf->max_buffer_size) - buf->buffer_size = buf->max_buffer_size; - - i_assert((uoff_t)buf->mmap_offset + buf->buffer_size <= - buf->start_offset + buf->size); - - buf->buffer = mmap(NULL, buf->buffer_size, PROT_READ, MAP_PRIVATE, - buf->fd, buf->mmap_offset); - if (buf->buffer == MAP_FAILED) { - buf->buf_errno = errno; - buf->buffer = NULL; - buf->buffer_size = 0; - buf->skip = buf->pos; - i_error("io_buffer_read_mmaped(): mmap() failed: %m"); - return -1; - } - - /* madvise() only if the mmap()ed area was larger than page size */ - if (buf->buffer_size > mmap_pagesize) { - (void)madvise((void *) buf->buffer, buf->buffer_size, - MADV_SEQUENTIAL); - } - - return io_buffer_set_mmaped_pos(buf); -} - -void io_buffer_set_start_offset(IOBuffer *buf, uoff_t offset) -{ - off_t diff; - - i_assert(offset <= buf->size); - - if (offset == buf->start_offset) - return; - - diff = (off_t)buf->start_offset - (off_t)offset; - buf->start_offset = offset; - buf->size += diff; - buf->limit += diff; - - io_buffer_reset(buf); - - buf->skip = buf->pos = buf->start_offset; -} - -void io_buffer_set_read_limit(IOBuffer *buf, uoff_t offset) -{ - i_assert(offset <= buf->size); - - if (offset == 0) - buf->limit = buf->size; - else { - i_assert(offset >= buf->offset); - - buf->limit = offset; - if (buf->offset + (buf->pos - buf->skip) > offset) - buf->pos = offset - buf->offset + buf->skip; - } -} - -ssize_t io_buffer_read(IOBuffer *buf) -{ - size_t size; - ssize_t ret; - - i_assert(!buf->transmit); - buf->receive = TRUE; - - if (buf->closed) - return -1; - - if (buf->mmaped) - return io_buffer_read_mmaped(buf); - - if (buf->pos == buf->buffer_size) { - if (buf->skip > 0) { - /* remove the unused bytes from beginning of buffer */ - io_buffer_compress(buf); - } else if (buf->max_buffer_size == 0 || - buf->buffer_size < buf->max_buffer_size) { - /* buffer is full - grow it */ - buffer_alloc_more(buf, IO_BUFFER_MIN_SIZE); - } - - if (buf->pos == buf->buffer_size) - return -2; /* buffer full */ - } - - size = buf->buffer_size - buf->pos; - if (buf->limit > 0) { - i_assert(buf->limit >= buf->offset); - if (size >= buf->limit - buf->offset) { - size = buf->limit - buf->offset; - if (size == 0) - return -1; - } - } - - /* fill the buffer */ - if (!buf->file) { - ret = net_receive(buf->fd, buf->buffer + buf->pos, size); - } else { - ret = read(buf->fd, buf->buffer + buf->pos, size); - if (ret == 0) - ret = -1; /* EOF */ - else if (ret < 0 && (errno == EINTR || errno == EAGAIN)) - ret = 0; - } - - if (ret < 0) { - /* disconnected */ - buf->buf_errno = errno; - return -1; - } - - buf->pos += ret; - return ret; -} - -static void io_read_data(void *context, int fd __attr_unused__, - IO io __attr_unused__) -{ - IOBufferBlockContext *ctx = context; - - if (io_buffer_read(ctx->inbuf) != 0) { - /* got data / error */ - io_loop_stop(ctx->ioloop); - } + buf->close(buf); } -ssize_t io_buffer_read_blocking(IOBuffer *buf) -{ - IOBufferBlockContext ctx; - Pool pool; - Timeout to; - ssize_t ret; - - /* first check if we can get some data */ - ret = io_buffer_read(buf); - if (ret != 0) - return ret; - - /* blocking now */ - - /* create a new I/O loop */ - memset(&ctx, 0, sizeof(ctx)); - pool = pool_create("io_buffer_read_blocking", 1024, FALSE); - ctx.ioloop = io_loop_create(pool); - ctx.inbuf = buf; - - buf->io = io_add(buf->fd, IO_READ, io_read_data, &ctx); - to = buf->timeout_msecs <= 0 ? NULL : - timeout_add(buf->timeout_msecs, block_loop_timeout, &ctx); - - io_loop_run(ctx.ioloop); - - if (buf->io != NULL) { - io_remove(buf->io); - buf->io = NULL; - } - - if (to != NULL) { - if (ctx.timeout && buf->timeout_func != NULL) { - /* call user-given timeout function */ - buf->timeout_func(buf->timeout_context, to); - } - timeout_remove(to); - } - - io_loop_destroy(ctx.ioloop); - pool_unref(pool); - - return buf->pos > buf->skip ? - (ssize_t) (buf->pos-buf->skip) : -1; -} - -void io_buffer_skip(IOBuffer *buf, uoff_t count) +void _io_buffer_set_max_size(_IOBuffer *buf, size_t max_size) { - uoff_t old_limit; - ssize_t ret; - - buf->offset += count; - - if (count <= buf->pos - buf->skip) { - buf->skip += count; - return; - } - - if (buf->mmaped) { - /* these point outside mmap now, next io_buffer_read_mmaped() - will fix them */ - buf->skip += count; - buf->pos = buf->skip; - } else { - if (buf->buffer_size == 0) - buffer_alloc_more(buf, IO_BUFFER_MIN_SIZE); - - count -= buf->skip; - - old_limit = buf->limit; - io_buffer_set_read_limit(buf, buf->offset + count); - - while ((ret = io_buffer_read_blocking(buf)) > 0) - io_buffer_skip(buf, ret); - - io_buffer_set_read_limit(buf, old_limit); - } -} - -int io_buffer_seek(IOBuffer *buf, uoff_t offset) -{ - uoff_t real_offset; - off_t ret; - - if (buf->closed) { - errno = EBADF; - return FALSE; - } - - real_offset = buf->start_offset + offset; - if (real_offset > OFF_T_MAX) { - errno = EINVAL; - return FALSE; - } - - if (buf->mmaped) { - /* first reset everything */ - io_buffer_reset(buf); - - /* then set the wanted position, next read will - pick up from there */ - buf->pos = buf->skip = real_offset; - } else { - ret = lseek(buf->fd, (off_t)real_offset, SEEK_SET); - if (ret < 0) - return FALSE; - - if (ret != (off_t)real_offset) { - errno = EINVAL; - return FALSE; - } - } - - buf->offset = offset; - return TRUE; -} - -/* skip the first LF, if it exists */ -static void io_buffer_skip_lf(IOBuffer *buf) -{ - if (!buf->last_cr || buf->skip >= buf->pos) - return; - - if (buf->buffer[buf->skip] == 10) { - if (buf->skip == buf->cr_lookup_pos) - buf->cr_lookup_pos++; - buf->skip++; - buf->offset++; - } - buf->last_cr = FALSE; + buf->set_max_size(buf, max_size); } -char *io_buffer_next_line(IOBuffer *buf) -{ - /* FIXME: buf->offset isn't updated right.. (skip_lf thing?) */ - char *ret_buf; - size_t i; - - i_assert(buf != NULL); - - io_buffer_skip_lf(buf); - if (buf->skip >= buf->pos) - return NULL; - - ret_buf = NULL; - for (i = buf->cr_lookup_pos; i < buf->pos; i++) { - if (buf->buffer[i] == 13 || buf->buffer[i] == 10) { - /* got it */ - buf->last_cr = buf->buffer[i] == 13; - buf->buffer[i] = '\0'; - ret_buf = (char *) buf->buffer + buf->skip; - - i++; - buf->offset += i - buf->skip; - buf->skip = i; - break; - } - } - - buf->cr_lookup_pos = i; - return ret_buf; -} - -unsigned char *io_buffer_get_data(IOBuffer *buf, size_t *size) -{ - io_buffer_skip_lf(buf); - - if (buf->skip >= buf->pos) { - *size = 0; - return NULL; - } - - *size = buf->pos - buf->skip; - return buf->buffer + buf->skip; -} - -int io_buffer_read_data_blocking(IOBuffer *buf, unsigned char **data, - size_t *size, size_t threshold) -{ - ssize_t ret; - - while (buf->pos - buf->skip <= threshold) { - /* we need more data */ - ret = io_buffer_read_blocking(buf); - if (ret < 0) { - if (ret == -2) - return -2; - else - break; - } - } - - *data = io_buffer_get_data(buf, size); - return *size > threshold ? 1 : *size > 0 ? 0 : -1; -} - -unsigned char *io_buffer_get_space(IOBuffer *buf, size_t size) +void _io_buffer_set_blocking(_IOBuffer *buf, int timeout_msecs, + TimeoutFunc timeout_func, void *context) { - i_assert(size > 0); - i_assert(size <= SSIZE_T_MAX); - i_assert(!buf->receive); - buf->transmit = TRUE; - - /* make sure we have enough space in buffer */ - if (buf->buffer_size - buf->pos < size && buf->skip > 0) { - /* remove the unused bytes from beginning of buffer */ - io_buffer_compress(buf); - } - - if (buf->buffer_size - buf->pos < size && - (buf->max_buffer_size == 0 || - size <= buf->max_buffer_size - buf->pos)) { - /* allocate more space */ - buffer_alloc_more(buf, size); - } - - if (buf->buffer_size - buf->pos < size) - return NULL; - - return buf->buffer + buf->pos; + buf->set_blocking(buf, timeout_msecs, timeout_func, context); } - -int io_buffer_send_buffer(IOBuffer *buf, size_t size) -{ - ssize_t ret; - - i_assert(size <= SSIZE_T_MAX); - i_assert(!buf->receive); - - if (buf->closed) - return -1; - - if (buf->pos == 0 && !buf->corked) { - /* buffer is empty, try to send the data immediately */ - ret = io_buffer_write(buf, buf->buffer, size); - if (ret < 0) - return -1; - - if ((size_t)ret == size) { - /* all sent */ - return 1; - } - - buf->skip += ret; - } - - buf->pos += size; - - if (buf->io == NULL && !buf->corked) { - buf->io = io_add_priority(buf->fd, buf->priority, IO_WRITE, - (IOFunc) buf_send, buf); - } - - return 1; -} - -int io_buffer_set_data(IOBuffer *buf, const void *data, size_t size) -{ - i_assert(!buf->mmaped); - - io_buffer_reset(buf); - - if (buf->buffer_size < size) { - buffer_alloc_more(buf, size); - if (buf->buffer_size < size) - return -2; - } - - buf->offset += size; - buf->offset -= buf->pos - buf->skip; - - memcpy(buf->buffer, data, size); - buf->pos = size; - buf->skip = 0; - return 1; -} - -int io_buffer_is_empty(IOBuffer *buf) -{ - return buf->skip >= buf->pos; -}
--- a/src/lib/iobuffer.h Sun Oct 13 18:52:19 2002 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,166 +0,0 @@ -#ifndef __IOBUFFER_H -#define __IOBUFFER_H - -#include "ioloop.h" - -typedef void (*IOBufferFlushFunc) (void *context, IOBuffer *buf); - -enum { - IOBUFFER_FLAG_AUTOCLOSE = 0x01 -}; - -struct _IOBuffer { - int fd; - - uoff_t start_offset; - uoff_t offset, size, limit; /* virtual offsets, 0 = start_offset */ - int buf_errno; /* set when write() or read() failed. */ - -/* private: */ - Pool pool; - IO io; - int refcount; - int priority; - - int timeout_msecs; - TimeoutFunc timeout_func; - void *timeout_context; - - IOBufferFlushFunc flush_func; - void *flush_context; - - unsigned char *buffer; - size_t cr_lookup_pos; /* used only when reading a line */ - - off_t mmap_offset; - size_t pos, skip; - size_t buffer_size, max_buffer_size; - - unsigned int file:1; /* reading/writing a file */ - unsigned int close_file:1; /* io_buffer_close() actually close()s fd */ - unsigned int mmaped:1; /* reading a file with mmap() */ - unsigned int closed:1; /* all further read/writes will return 0 */ - unsigned int transmit:1; /* this is a transmit buffer */ - unsigned int receive:1; /* this is a receive buffer */ - unsigned int last_cr:1; /* we're expecting a LF to be skipped in - next call to io_buffer_next_line() */ - unsigned int blocking:1; /* writes block if buffer is full */ - unsigned int corked:1; /* TCP_CORK set */ -}; - -/* Create an I/O buffer. It can be used for either sending or receiving data, - NEVER BOTH AT SAME TIME. */ -IOBuffer *io_buffer_create(int fd, Pool pool, int priority, - size_t max_buffer_size); -/* Same as io_buffer_create(), but specify that we're reading/writing file. */ -IOBuffer *io_buffer_create_file(int fd, Pool pool, size_t max_buffer_size, - int flags); -/* Read the file by mmap()ing it in blocks. stop_offset specifies where to - stop reading, or 0 to end of file. */ -IOBuffer *io_buffer_create_mmap(int fd, Pool pool, size_t block_size, - uoff_t start_offset, uoff_t size, - int flags); - -/* Reference counting. References start from 1, so calling io_buffer_unref() - destroys the buffer if io_buffer_ref() is never used. */ -void io_buffer_ref(IOBuffer *buf); -void io_buffer_unref(IOBuffer *buf); - -/* Mark the buffer closed. Any sends/reads after this will return -1. - The data already in buffer can be used, and the remaining output buffer - will be sent. */ -void io_buffer_close(IOBuffer *buf); -/* Reset all pointers so that the buffer looks empty, the actual data is - not touched and can be used. */ -void io_buffer_reset(IOBuffer *buf); - -/* Change the memory pool used by the buffer. Data already in - buffer will be transferred to new buffer. */ -IOBuffer *io_buffer_set_pool(IOBuffer *buf, Pool pool); -/* Change the maximum size for buffer to grow. */ -void io_buffer_set_max_size(IOBuffer *buf, size_t max_size); -/* Change buffer's blocking state. The blocking state in fd itself isn't - changed, and it's not needed to be blocking. This affects two things: - - When buffer reaches max_size, it will block until all the data has been - sent or timeout has been reached. Setting max_size to 0 disables this - (default). Setting timeout_msecs to 0 may block infinitely, or until - socket is closed. - - Sets the timeout for io_buffer_read_blocking(). If max_size is non-zero, - it acts the same as io_buffer_set_max_size(). - - timeout_func is called with both cases when timeout occurs. -*/ -void io_buffer_set_blocking(IOBuffer *buf, size_t max_size, - int timeout_msecs, TimeoutFunc timeout_func, - void *context); - -/* Set TCP_CORK on if supported, ie. don't send out partial frames. - io_buffer_send_flush() removes the cork. */ -void io_buffer_cork(IOBuffer *buf); - -/* Returns 1 if all was ok, -1 if disconnected, -2 if buffer is full */ -int io_buffer_send(IOBuffer *buf, const void *data, size_t size); -/* Send data from input buffer to output buffer using the fastest - possible method. Returns 1 if all sent or -1 if disconnected. - Note that this function may block. */ -int io_buffer_send_iobuffer(IOBuffer *outbuf, IOBuffer *inbuf, - uoff_t long_size); -/* Flush the output buffer, blocks until all is sent. If - io_buffer_set_send_blocking() is called, it's timeout settings are used. */ -void io_buffer_send_flush(IOBuffer *buf); -/* Call specified function when the whole transmit buffer has been sent. - If the buffer is empty already, the function will be called immediately. - The function will be called only once. */ -void io_buffer_send_flush_callback(IOBuffer *buf, IOBufferFlushFunc func, - void *context); - -/* Change the start_offset and call io_buffer_reset(). Doesn't do anything - if offset is the same as existing start_offset. */ -void io_buffer_set_start_offset(IOBuffer *buf, uoff_t offset); - -/* IO buffer won't be read past specified offset. Giving 0 as offset removes - the limit. */ -void io_buffer_set_read_limit(IOBuffer *buf, uoff_t offset); - -/* Returns number of bytes read if read was ok, - -1 if disconnected / EOF, -2 if the buffer is full */ -ssize_t io_buffer_read(IOBuffer *buf); -/* Blocking read, doesn't return until at least one byte is read, or until - socket is disconnected or timeout has occured. Note that the fd must be - nonblocking, or the timeout doesn't work. Returns number of bytes read - (never 0), -1 if error or -2 if buffer is full. */ -ssize_t io_buffer_read_blocking(IOBuffer *buf); -/* Skip forward a number of bytes */ -void io_buffer_skip(IOBuffer *buf, uoff_t count); -/* Seek to specified position from beginning of file. This works only for - files. Returns TRUE if successful. */ -int io_buffer_seek(IOBuffer *buf, uoff_t offset); -/* Returns the next line from input buffer, or NULL if more data is needed - to make a full line. NOTE: call to io_buffer_read() invalidates the - returned data. */ -char *io_buffer_next_line(IOBuffer *buf); -/* Returns pointer to beginning of data in buffer, - or NULL if there's no data. */ -unsigned char *io_buffer_get_data(IOBuffer *buf, size_t *size); -/* Like io_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 io_buffer_read_data_blocking(IOBuffer *buf, unsigned char **data, - size_t *size, size_t threshold); - -/* Returns a pointer to buffer wanted amount of space, - or NULL if size is too big. */ -unsigned char *io_buffer_get_space(IOBuffer *buf, size_t size); -/* Send data saved to buffer from io_buffer_get_space(). - Returns -1 if disconnected. */ -int io_buffer_send_buffer(IOBuffer *buf, size_t size); - -/* Put data to buffer as if it was received. - Returns 1 if successful, -2 if buffer isn't big enough. */ -int io_buffer_set_data(IOBuffer *buf, const void *data, size_t size); -/* Returns TRUE if there's nothing in buffer. */ -int io_buffer_is_empty(IOBuffer *buf); - -#endif
--- a/src/lib/lib.h Sun Oct 13 18:52:19 2002 +0300 +++ b/src/lib/lib.h Mon Oct 14 02:49:11 2002 +0300 @@ -18,7 +18,8 @@ typedef struct _Timeout *Timeout; typedef struct _IPADDR IPADDR; -typedef struct _IOBuffer IOBuffer; +typedef struct _IBuffer IBuffer; +typedef struct _OBuffer OBuffer; typedef struct _TempString TempString; #include "compat.h"
--- a/src/lib/network.c Sun Oct 13 18:52:19 2002 +0300 +++ b/src/lib/network.c Mon Oct 14 02:49:11 2002 +0300 @@ -225,11 +225,13 @@ #endif } -void net_set_cork(int fd __attr_unused__, int cork __attr_unused__) +int net_set_cork(int fd __attr_unused__, int cork __attr_unused__) { #ifdef TCP_CORK - if (setsockopt(fd, SOL_TCP, TCP_CORK, &cork, sizeof(cork)) < 0) - i_error("setsockopt(TCP_CORK) failed: %m"); + return setsockopt(fd, SOL_TCP, TCP_CORK, &cork, sizeof(cork)); +#else + errno = ENOPROTOOPT; + return -1; #endif }
--- a/src/lib/network.h Sun Oct 13 18:52:19 2002 +0300 +++ b/src/lib/network.h Mon Oct 14 02:49:11 2002 +0300 @@ -54,8 +54,9 @@ /* Set socket blocking/nonblocking */ void net_set_nonblock(int fd, int nonblock); -/* Set TCP_CORK if supported, ie. don't send out partial frames. */ -void net_set_cork(int fd, int cork); +/* Set TCP_CORK if supported, ie. don't send out partial frames. + Returns 0 if ok, -1 if failed. */ +int net_set_cork(int fd, int cork); /* Listen for connections on a socket */ int net_listen(IPADDR *my_ip, unsigned int *port);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/lib/obuffer-file.c Mon Oct 14 02:49:11 2002 +0300 @@ -0,0 +1,687 @@ +/* + 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 "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 BUFFER_IS_BLOCKING(fbuf) \ + ((fbuf)->timeout_msecs != 0) + +#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; + TimeoutFunc timeout_func; + 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; + +typedef struct { + IOLoop ioloop; + FileOBuffer *fbuf; + uoff_t sent; + int timeout; + + IBuffer *inbuf; + struct iovec iov[3]; + unsigned int iov_len; +} IOLoopWriteContext; + +static void _close(_IOBuffer *buf) +{ + FileOBuffer *fbuf = (FileOBuffer *) buf; + + 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; + } +} + +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, + TimeoutFunc timeout_func, void *context) +{ + FileOBuffer *fbuf = (FileOBuffer *) buf; + + fbuf->timeout_msecs = timeout_msecs; + fbuf->timeout_func = timeout_func; + fbuf->timeout_context = context; +} + +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 (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, unsigned 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) + return -1; + + update_iovec(iov, iov_size, ret); + update_buffer(fbuf, ret); + fbuf->obuf.obuffer.v_offset += ret; + + return ret; +} + +static void ioloop_send(IOLoopWriteContext *ctx) +{ + if (o_buffer_writev(ctx->fbuf, ctx->iov, ctx->iov_len) < 0 || + ctx->iov[ctx->iov_len-1].iov_len == 0) { + /* error / all sent */ + io_loop_stop(ctx->ioloop); + } +} + +static void ioloop_timeout(void *context, Timeout timeout __attr_unused__) +{ + IOLoopWriteContext *ctx = context; + + ctx->timeout = TRUE; + io_loop_stop(ctx->ioloop); +} + +static int o_buffer_ioloop(FileOBuffer *fbuf, IOLoopWriteContext *ctx, + void (*send_func)(IOLoopWriteContext *ctx)) +{ + Timeout to; + IO io; + + /* close old IO */ + if (fbuf->io != NULL) + io_remove(fbuf->io); + + t_push(); + + /* create a new I/O loop */ + ctx->ioloop = io_loop_create(data_stack_pool); + ctx->fbuf = fbuf; + + io = io_add(fbuf->fd, IO_WRITE, (IOFunc) send_func, ctx); + to = fbuf->timeout_msecs <= 0 ? NULL : + timeout_add(fbuf->timeout_msecs, ioloop_timeout, ctx); + + io_loop_run(ctx->ioloop); + + io_remove(io); + + if (to != NULL) { + if (ctx->timeout && fbuf->timeout_func != NULL) { + /* call user-given timeout function */ + fbuf->timeout_func(fbuf->timeout_context, to); + } + timeout_remove(to); + } + + io_loop_destroy(ctx->ioloop); + t_pop(); + + return fbuf->obuf.obuffer.closed ? -1 : 1; +} + +/* 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) +{ + IOLoopWriteContext ctx; + + memset(&ctx, 0, sizeof(ctx)); + + ctx.iov_len = o_buffer_fill_iovec(fbuf, ctx.iov); + if (size > 0) { + ctx.iov[ctx.iov_len].iov_base = (void *) data; + ctx.iov[ctx.iov_len].iov_len = size; + ctx.iov_len++; + } + + return o_buffer_ioloop(fbuf, &ctx, ioloop_send); +} + +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; +} + +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.v_offset = 0; + 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 && size > fbuf->max_buffer_size) + 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; + + if (IS_BUFFER_EMPTY(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 void ioloop_sendfile(IOLoopWriteContext *ctx) +{ + OBuffer *outbuf; + uoff_t offset, send_size; + ssize_t ret; + int in_fd; + + outbuf = &ctx->fbuf->obuf.obuffer; + in_fd = i_buffer_get_fd(ctx->inbuf); + i_assert(in_fd != -1); + + offset = ctx->inbuf->v_offset; + send_size = ctx->inbuf->v_limit - offset; + + ret = safe_sendfile(ctx->fbuf->fd, in_fd, &offset, + MAX_SSIZE_T(send_size)); + if (ret < 0) { + if (errno != EINTR && errno != EAGAIN) { + outbuf->buf_errno = errno; + o_buffer_close(outbuf); + } + ret = 0; + } + + i_buffer_skip(ctx->inbuf, (size_t)ret); + outbuf->v_offset += ret; + + if (outbuf->closed || (size_t)ret == send_size) + io_loop_stop(ctx->ioloop); +} + +static void ioloop_copy(IOLoopWriteContext *ctx) +{ + const unsigned char *data; + size_t size; + int pos; + + i_assert(ctx->iov_len <= 2); + + (void)i_buffer_read_data(ctx->inbuf, &data, &size, O_BUFFER_MIN_SIZE-1); + + pos = ctx->iov_len++; + ctx->iov[pos].iov_base = (void *) data; + ctx->iov[pos].iov_len = size; + + if (o_buffer_writev(ctx->fbuf, ctx->iov, ctx->iov_len) < 0 || + ctx->iov[ctx->iov_len-1].iov_len == 0) { + /* error / all sent */ + io_loop_stop(ctx->ioloop); + } + + i_buffer_skip(ctx->inbuf, size - ctx->iov[pos].iov_len); + + do { + ctx->iov_len--; + } while (ctx->iov_len > 0 && ctx->iov[ctx->iov_len-1].iov_len == 0); +} + +static off_t o_buffer_sendfile(_OBuffer *outbuf, IBuffer *inbuf) +{ + FileOBuffer *foutbuf = (FileOBuffer *) outbuf; + IOLoopWriteContext ctx; + uoff_t offset, send_size; + ssize_t s_ret; + int in_fd; + + in_fd = i_buffer_get_fd(inbuf); + if (in_fd == -1) { + outbuf->obuffer.buf_errno = EINVAL; + return -1; + } + + /* flush out any data in buffer */ + if (buffer_flush(foutbuf) < 0) + return -1; + + /* first try if we can do it with a single sendfile() call */ + offset = inbuf->v_offset; + send_size = inbuf->v_limit - offset; + + s_ret = safe_sendfile(foutbuf->fd, in_fd, &offset, + MAX_SSIZE_T(send_size)); + if (s_ret < 0) { + if (errno != EINTR && errno != EAGAIN) { + outbuf->obuffer.buf_errno = errno; + return -1; + } + s_ret = 0; + } + + i_buffer_skip(inbuf, (size_t)s_ret); + outbuf->obuffer.v_offset += s_ret; + + if ((uoff_t)s_ret == send_size) { + /* yes, all sent */ + return (off_t)s_ret; + } + + memset(&ctx, 0, sizeof(ctx)); + + ctx.fbuf = foutbuf; + ctx.inbuf = inbuf; + + if (o_buffer_ioloop(foutbuf, &ctx, ioloop_sendfile) < 0) { + if (outbuf->obuffer.buf_errno == EINVAL) { + /* this shouldn't happen, must be a bug. It would also + mess up later if we let this pass. */ + i_panic("o_buffer_sendfile() failed: %m"); + } + return -1; + } else { + return (off_t)ctx.sent; + } +} + +static off_t _send_ibuffer(_OBuffer *outbuf, IBuffer *inbuf) +{ + IOLoopWriteContext ctx; + off_t ret; + + i_assert(inbuf->v_limit <= OFF_T_MAX); + i_assert(inbuf->v_offset <= inbuf->v_limit); + + ret = o_buffer_sendfile(outbuf, inbuf); + if (ret >= 0 || outbuf->obuffer.buf_errno != EINVAL) + return ret; + + /* sendfile() not supported (with this fd), fallback to + regular sending */ + + /* create blocking send loop */ + memset(&ctx, 0, sizeof(ctx)); + + ctx.fbuf = (FileOBuffer *) outbuf; + ctx.iov_len = o_buffer_fill_iovec(ctx.fbuf, ctx.iov); + ctx.inbuf = inbuf; + + if (o_buffer_ioloop(ctx.fbuf, &ctx, ioloop_copy) < 0) + return -1; + else + return (off_t)ctx.sent; +} + +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); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/lib/obuffer-internal.h Mon Oct 14 02:49:11 2002 +0300 @@ -0,0 +1,27 @@ +#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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/lib/obuffer.c Mon Oct 14 02:49:11 2002 +0300 @@ -0,0 +1,121 @@ +/* + 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, + TimeoutFunc timeout_func, 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); +} + +ssize_t 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; + + 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; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/lib/obuffer.h Mon Oct 14 02:49:11 2002 +0300 @@ -0,0 +1,56 @@ +#ifndef __OBUFFER_H +#define __OBUFFER_H + +#include "ioloop.h" /* TimeoutFunc */ + +struct _OBuffer { + uoff_t v_offset; /* relative to start 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, also calling timeout_func if it's + set. The blocking state in file descriptor isn't changed, but for timeout + to work it must be in non-blocking state. */ +void o_buffer_set_blocking(OBuffer *buf, int timeout_msecs, + TimeoutFunc timeout_func, 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 and v_offset is set to 0. + 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. */ +off_t o_buffer_send_ibuffer(OBuffer *outbuf, IBuffer *inbuf); + +#endif
--- a/src/login/auth-connection.c Sun Oct 13 18:52:19 2002 +0300 +++ b/src/login/auth-connection.c Mon Oct 14 02:49:11 2002 +0300 @@ -3,7 +3,8 @@ #include "common.h" #include "hash.h" #include "network.h" -#include "iobuffer.h" +#include "ibuffer.h" +#include "obuffer.h" #include "auth-connection.h" #include <unistd.h> @@ -20,7 +21,8 @@ char *path; int fd; IO io; - IOBuffer *inbuf, *outbuf; + IBuffer *inbuf; + OBuffer *outbuf; int auth_process; AuthMethod available_auth_methods; @@ -70,10 +72,10 @@ conn->path = i_strdup(path); conn->fd = fd; conn->io = io_add(fd, IO_READ, auth_input, conn); - conn->inbuf = io_buffer_create(fd, default_pool, IO_PRIORITY_HIGH, - MAX_INBUF_SIZE); - conn->outbuf = io_buffer_create(fd, default_pool, IO_PRIORITY_DEFAULT, - MAX_OUTBUF_SIZE); + conn->inbuf = i_buffer_create_file(fd, default_pool, MAX_INBUF_SIZE, + FALSE); + conn->outbuf = o_buffer_create_file(fd, default_pool, MAX_OUTBUF_SIZE, + IO_PRIORITY_DEFAULT, FALSE); conn->requests = hash_create(default_pool, 100, NULL, NULL); conn->next = auth_connections; @@ -118,8 +120,8 @@ (void)close(conn->fd); io_remove(conn->io); - io_buffer_unref(conn->inbuf); - io_buffer_unref(conn->outbuf); + i_buffer_unref(conn->inbuf); + o_buffer_unref(conn->outbuf); i_free(conn->path); i_free(conn); } @@ -133,7 +135,7 @@ found = FALSE; for (conn = auth_connections; conn != NULL; conn = conn->next) { if ((conn->available_auth_methods & method)) { - if (io_buffer_get_space(conn->outbuf, size) != NULL) + if (o_buffer_have_space(conn->outbuf, size) > 0) return conn; found = TRUE; @@ -175,7 +177,7 @@ } static void auth_handle_reply(AuthConnection *conn, AuthReplyData *reply_data, - unsigned char *data) + const unsigned char *data) { AuthRequest *request; @@ -204,10 +206,10 @@ { AuthConnection *conn = context; AuthInitData init_data; - unsigned char *data; + const unsigned char *data; size_t size; - switch (io_buffer_read(conn->inbuf)) { + switch (i_buffer_read(conn->inbuf)) { case 0: return; case -1: @@ -223,12 +225,12 @@ return; } - data = io_buffer_get_data(conn->inbuf, &size); + data = i_buffer_get_data(conn->inbuf, &size); if (!conn->init_received) { if (size == sizeof(AuthInitData)) { memcpy(&init_data, data, sizeof(AuthInitData)); - io_buffer_skip(conn->inbuf, sizeof(AuthInitData)); + i_buffer_skip(conn->inbuf, sizeof(AuthInitData)); auth_handle_init(conn, &init_data); } else if (size > sizeof(AuthInitData)) { @@ -242,14 +244,14 @@ } if (!conn->in_reply_received) { - data = io_buffer_get_data(conn->inbuf, &size); + data = i_buffer_get_data(conn->inbuf, &size); if (size < sizeof(AuthReplyData)) return; memcpy(&conn->in_reply, data, sizeof(AuthReplyData)); data += sizeof(AuthReplyData); size -= sizeof(AuthReplyData); - io_buffer_skip(conn->inbuf, sizeof(AuthReplyData)); + i_buffer_skip(conn->inbuf, sizeof(AuthReplyData)); conn->in_reply_received = TRUE; } @@ -259,7 +261,7 @@ /* we've got a full reply */ conn->in_reply_received = FALSE; auth_handle_reply(conn, &conn->in_reply, data); - io_buffer_skip(conn->inbuf, conn->in_reply.data_size); + i_buffer_skip(conn->inbuf, conn->in_reply.data_size); } int auth_init_request(AuthMethod method, AuthCallback callback, @@ -290,8 +292,8 @@ request_data.type = AUTH_REQUEST_INIT; request_data.method = request->method; request_data.id = request->id; - if (io_buffer_send(request->conn->outbuf, &request_data, - sizeof(request_data)) < 0) + if (o_buffer_send(request->conn->outbuf, &request_data, + sizeof(request_data)) < 0) auth_connection_destroy(request->conn); return TRUE; } @@ -307,10 +309,10 @@ request_data.id = request->id; request_data.data_size = data_size; - if (io_buffer_send(request->conn->outbuf, &request_data, - sizeof(request_data)) < 0) + if (o_buffer_send(request->conn->outbuf, &request_data, + sizeof(request_data)) < 0) auth_connection_destroy(request->conn); - else if (io_buffer_send(request->conn->outbuf, data, data_size) < 0) + else if (o_buffer_send(request->conn->outbuf, data, data_size) < 0) auth_connection_destroy(request->conn); }
--- a/src/login/client-authenticate.c Sun Oct 13 18:52:19 2002 +0300 +++ b/src/login/client-authenticate.c Mon Oct 14 02:49:11 2002 +0300 @@ -2,7 +2,8 @@ #include "common.h" #include "base64.h" -#include "iobuffer.h" +#include "ibuffer.h" +#include "obuffer.h" #include "temp-string.h" #include "auth-connection.h" #include "client.h" @@ -71,7 +72,7 @@ client_send_tagline(client, msg != NULL ? msg : "NO Authentication failed."); - io_buffer_send_flush(client->outbuf); + o_buffer_flush(client->outbuf); /* get back to normal client input */ if (client->io != NULL) @@ -109,11 +110,11 @@ t_push(); base64_data = base64_encode(data, size); - io_buffer_send(client->outbuf, "+ ", 2); - io_buffer_send(client->outbuf, base64_data, strlen(base64_data)); - io_buffer_send(client->outbuf, "\r\n", 2); + o_buffer_send(client->outbuf, "+ ", 2); + o_buffer_send(client->outbuf, base64_data, strlen(base64_data)); + o_buffer_send(client->outbuf, "\r\n", 2); - io_buffer_send_flush(client->outbuf); + o_buffer_flush(client->outbuf); t_pop(); } @@ -239,7 +240,7 @@ if (!client_read(client)) return; - line = io_buffer_next_line(client->inbuf); + line = i_buffer_next_line(client->inbuf); if (line == NULL) return;
--- a/src/login/client.c Sun Oct 13 18:52:19 2002 +0300 +++ b/src/login/client.c Mon Oct 14 02:49:11 2002 +0300 @@ -2,7 +2,8 @@ #include "common.h" #include "hash.h" -#include "iobuffer.h" +#include "ibuffer.h" +#include "obuffer.h" #include "client.h" #include "client-authenticate.h" #include "ssl-proxy.h" @@ -49,7 +50,7 @@ } client_send_tagline(client, "OK Begin TLS negotiation now."); - io_buffer_send_flush(client->outbuf); + o_buffer_flush(client->outbuf); /* must be removed before ssl_proxy_new(), since it may io_add() the same fd. */ @@ -59,11 +60,15 @@ if (fd_ssl != -1) { client->tls = TRUE; client->fd = fd_ssl; - client->inbuf->fd = fd_ssl; - client->outbuf->fd = fd_ssl; + + i_buffer_unref(client->inbuf); + o_buffer_unref(client->outbuf); - i_assert(client->inbuf->io == NULL); - i_assert(client->outbuf->io == NULL); + client->inbuf = i_buffer_create_file(fd_ssl, default_pool, + 8192, FALSE); + client->outbuf = o_buffer_create_file(fd_ssl, default_pool, + 1024, IO_PRIORITY_DEFAULT, + FALSE); } else { client_send_line(client, " * BYE TLS handehake failed."); client_destroy(client, "TLS handshake failed"); @@ -89,7 +94,7 @@ int client_read(Client *client) { - switch (io_buffer_read(client->inbuf)) { + switch (i_buffer_read(client->inbuf)) { case -2: /* buffer full */ client_send_line(client, "* BYE Input buffer full, aborting"); @@ -181,9 +186,9 @@ return; client_ref(client); - io_buffer_cork(client->outbuf); + o_buffer_cork(client->outbuf); - while ((line = io_buffer_next_line(client->inbuf)) != NULL) { + while ((line = i_buffer_next_line(client->inbuf)) != NULL) { /* split the arguments, make sure we have at least tag + command */ i_free(client->tag); @@ -198,7 +203,7 @@ } if (client_unref(client)) - io_buffer_send_flush(client->outbuf); + o_buffer_flush(client->outbuf); } static void client_hash_destroy_oldest(void *key, void *value __attr_unused__, @@ -255,10 +260,9 @@ memcpy(&client->ip, ip, sizeof(IPADDR)); client->fd = fd; client->io = io_add(fd, IO_READ, client_input, client); - client->inbuf = io_buffer_create(fd, default_pool, - IO_PRIORITY_DEFAULT, 8192); - client->outbuf = io_buffer_create(fd, default_pool, - IO_PRIORITY_DEFAULT, 1024); + client->inbuf = i_buffer_create_file(fd, default_pool, 8192, FALSE); + client->outbuf = o_buffer_create_file(fd, default_pool, 1024, + IO_PRIORITY_DEFAULT, FALSE); client->last_input = ioloop_time; hash_insert(clients, client, client); @@ -273,8 +277,8 @@ hash_remove(clients, client); - io_buffer_close(client->inbuf); - io_buffer_close(client->outbuf); + i_buffer_close(client->inbuf); + o_buffer_close(client->outbuf); if (client->io != NULL) { io_remove(client->io); @@ -297,8 +301,8 @@ if (--client->refcount > 0) return TRUE; - io_buffer_unref(client->inbuf); - io_buffer_unref(client->outbuf); + i_buffer_unref(client->inbuf); + o_buffer_unref(client->outbuf); i_free(client->tag); i_free(client->plain_login); @@ -308,8 +312,8 @@ void client_send_line(Client *client, const char *line) { - io_buffer_send(client->outbuf, line, strlen(line)); - io_buffer_send(client->outbuf, "\r\n", 2); + o_buffer_send(client->outbuf, line, strlen(line)); + o_buffer_send(client->outbuf, "\r\n", 2); } void client_send_tagline(Client *client, const char *line)
--- a/src/login/client.h Sun Oct 13 18:52:19 2002 +0300 +++ b/src/login/client.h Mon Oct 14 02:49:11 2002 +0300 @@ -10,7 +10,8 @@ int fd; IO io; - IOBuffer *inbuf, *outbuf; + IBuffer *inbuf; + OBuffer *outbuf; time_t last_input; char *tag;
--- a/src/master/auth-process.c Sun Oct 13 18:52:19 2002 +0300 +++ b/src/master/auth-process.c Mon Oct 14 02:49:11 2002 +0300 @@ -2,7 +2,7 @@ #include "common.h" #include "network.h" -#include "iobuffer.h" +#include "obuffer.h" #include "restrict-access.h" #include "auth-process.h" @@ -20,7 +20,7 @@ pid_t pid; int fd; IO io; - IOBuffer *outbuf; + OBuffer *outbuf; unsigned int reply_pos; char reply_buf[sizeof(AuthCookieReplyData)]; @@ -123,8 +123,9 @@ p->pid = pid; p->fd = fd; p->io = io_add(fd, IO_READ, auth_process_input, p); - p->outbuf = io_buffer_create(fd, default_pool, IO_PRIORITY_DEFAULT, - sizeof(AuthCookieRequestData)*100); + p->outbuf = o_buffer_create_file(fd, default_pool, + sizeof(AuthCookieRequestData)*100, + IO_PRIORITY_DEFAULT, FALSE); p->next_request = &p->requests; @@ -154,7 +155,7 @@ (void)unlink(t_strconcat(set_login_dir, "/", p->name, NULL)); - io_buffer_unref(p->outbuf); + o_buffer_unref(p->outbuf); io_remove(p->io); (void)close(p->fd); i_free(p->name); @@ -268,7 +269,7 @@ req.id = id; memcpy(req.cookie, cookie, AUTH_COOKIE_SIZE); - if (io_buffer_send(process->outbuf, &req, sizeof(req)) < 0) + if (o_buffer_send(process->outbuf, &req, sizeof(req)) < 0) auth_process_destroy(process); push_request(process, id, callback, context);
--- a/src/master/login-process.c Sun Oct 13 18:52:19 2002 +0300 +++ b/src/master/login-process.c Mon Oct 14 02:49:11 2002 +0300 @@ -2,7 +2,7 @@ #include "common.h" #include "network.h" -#include "iobuffer.h" +#include "obuffer.h" #include "fdpass.h" #include "restrict-access.h" #include "login-process.h" @@ -19,7 +19,7 @@ pid_t pid; int fd; IO io; - IOBuffer *outbuf; + OBuffer *outbuf; unsigned int destroyed:1; } LoginProcess; @@ -68,7 +68,7 @@ reply.id = request->login_id; process = request->process; - if (io_buffer_send(process->outbuf, &reply, sizeof(reply)) < 0) + if (o_buffer_send(process->outbuf, &reply, sizeof(reply)) < 0) login_process_destroy(process); (void)close(request->fd); @@ -139,8 +139,9 @@ p->pid = pid; p->fd = fd; p->io = io_add(fd, IO_READ, login_process_input, p); - p->outbuf = io_buffer_create(fd, default_pool, IO_PRIORITY_DEFAULT, - sizeof(MasterReply)*10); + p->outbuf = o_buffer_create_file(fd, default_pool, + sizeof(MasterReply)*10, + IO_PRIORITY_DEFAULT, FALSE); hash_insert(processes, POINTER_CAST(pid), p); return p; @@ -152,7 +153,7 @@ return; p->destroyed = TRUE; - io_buffer_close(p->outbuf); + o_buffer_close(p->outbuf); io_remove(p->io); (void)close(p->fd); @@ -165,7 +166,7 @@ if (--p->refcount > 0) return; - io_buffer_unref(p->outbuf); + o_buffer_unref(p->outbuf); i_free(p); }
--- a/src/master/settings.c Sun Oct 13 18:52:19 2002 +0300 +++ b/src/master/settings.c Mon Oct 14 02:49:11 2002 +0300 @@ -1,7 +1,7 @@ /* Copyright (C) 2002 Timo Sirainen */ #include "lib.h" -#include "iobuffer.h" +#include "ibuffer.h" #include "settings.h" #include <stdio.h> @@ -124,6 +124,18 @@ } } +static void auth_settings_verify(void) +{ + AuthConfig *auth; + + for (auth = auth_processes_config; auth != NULL; auth = auth->next) { + if (access(set_imap_executable, X_OK) == -1) { + i_fatal("Can't use auth executable %s: %m", + auth->executable); + } + } +} + static void settings_verify(void) { get_login_uid(); @@ -150,6 +162,8 @@ i_fatal("first_valid_uid can't be larger than last_valid_uid"); if (set_first_valid_gid < set_last_valid_gid) i_fatal("first_valid_gid can't be larger than last_valid_gid"); + + auth_settings_verify(); } static AuthConfig *auth_config_new(const char *name) @@ -170,6 +184,9 @@ { AuthConfig *auth; + if (strchr(name, '/') != NULL) + return "Authentication process name must not contain '/'"; + for (auth = auth_processes_config; auth != NULL; auth = auth->next) { if (strcmp(auth->name, name) == 0) { return "Authentication process already exists " @@ -277,7 +294,7 @@ void settings_read(const char *path) { - IOBuffer *inbuf; + IBuffer *inbuf; const char *errormsg; char *line, *key, *p; int fd, linenum; @@ -289,11 +306,11 @@ i_fatal("Can't open configuration file %s: %m", path); linenum = 0; - inbuf = io_buffer_create_file(fd, default_pool, 2048, TRUE); + inbuf = i_buffer_create_file(fd, default_pool, 2048, TRUE); for (;;) { - line = io_buffer_next_line(inbuf); + line = i_buffer_next_line(inbuf); if (line == NULL) { - if (io_buffer_read(inbuf) <= 0) + if (i_buffer_read(inbuf) <= 0) break; continue; } @@ -338,7 +355,7 @@ } }; - io_buffer_unref(inbuf); + i_buffer_unref(inbuf); settings_verify(); }