iobuffer.c revision 5f6368ee09ba3edfb9b582199c2730a7b5517a10
/*
iobuffer.c : Input/output transmit 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,
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 "ioloop.h"
#include "iobuffer.h"
#include "mmap-util.h"
#include "sendfile-util.h"
#include "network.h"
#include <unistd.h>
static unsigned int mmap_pagesize = 0;
static unsigned int mmap_pagemask = 0;
unsigned int max_buffer_size)
{
return buf;
}
unsigned int max_buffer_size)
{
return buf;
}
{
/* block size must be page aligned, and at least two pages long */
if (mmap_pagesize == 0) {
mmap_pagesize = getpagesize();
}
else if ((block_size & mmap_pagemask) != 0) {
block_size &= ~mmap_pagemask;
}
/* set offsets */
if (start_offset < 0 || stop_offset < 0) {
i_error("io_buffer_create_mmap(): lseek() failed: %m");
}
if (start_offset > stop_offset)
}
return buf;
}
{
return;
else
}
}
{
return;
}
{
buf->buffer_size = 0;
}
}
{
}
return newbuf;
}
{
}
void *context)
{
}
{
int ret;
if (size == 0)
return 0;
ret = 0;
return ret;
}
{
int ret;
} else {
}
if (ret < 0) {
} else {
/* everything sent */
/* call flush function */
/* remove cork */
}
}
}
}
}
{
return FALSE;
}
return TRUE;
}
typedef struct {
const char *data;
unsigned int size;
int timeout;
{
int ret;
} else {
/* send the data */
if (ret < 0) {
} else {
}
}
}
{
}
{
int save_errno;
/* close old IO */
/* create a new I/O loop */
save_errno = errno;
/* remove cork */
}
}
/* call user-given timeout function */
}
}
errno = save_errno;
}
unsigned int size)
{
}
{
}
{
buf->buffer_size =
/* pool limit exceeded */
}
}
{
buf->cr_lookup_pos = 0;
else
}
{
return -1;
/* if we're corked, first try adding it to buffer. if it's larger
than the buffer, send it immediately. */
for (i = 0; i < 2; i++) {
/* buffer is empty, try to send the data immediately */
if (ret < 0) {
/* disconnected */
return -1;
}
}
if (size == 0) {
/* all sent */
return 1;
}
break;
if (corked)
else {
/* if we don't have space, we block */
}
return -2;
}
}
/* add to buffer */
}
return 1;
}
{
int ret;
if (ret < 0) {
ret = 0;
}
}
unsigned int size)
{
int ret;
/* first try if we can do it with a single sendfile() call */
if (ret < 0) {
return -1;
ret = 0;
}
/* yes, all sent */
return 1;
}
/* this shouldn't happen, must be a bug. It would also
mess up later if we let this pass. */
i_fatal("io_buffer_sendfile() failed: %m");
}
return ret;
}
{
unsigned char *in_data;
unsigned int size;
int ret;
&size, 0)) <= 0) {
if (ret == -1) {
/* disconnected */
break;
}
}
/* send the data */
}
unsigned int size)
{
unsigned char *in_data;
unsigned int in_size;
int ret;
return ret;
/* sendfile() not supported (with this fd), fallback to
regular sending */
/* see if we can do it at one go */
if (ret == -1)
return -1;
if (ret < 0) {
return -1;
}
/* all sent */
return 1;
}
/* create blocking send loop */
}
{
return;
}
void *context)
{
return;
}
}
{
unsigned int aligned_skip;
/* end of file is already mapped */
return -1;
}
/* didn't skip enough bytes */
return -2;
}
i_error("io_buffer_read_mmaped(): mmap() failed: %m");
return -1;
}
return buf->buffer_size;
}
{
int ret;
return -1;
/* remove the unused bytes from beginning of buffer */
} else if (buf->max_buffer_size == 0 ||
/* buffer is full - grow it */
}
return -2; /* buffer full */
}
/* fill the buffer */
} else {
if (ret == 0)
ret = 0;
}
if (ret < 0) {
/* disconnected */
return -1;
}
return ret;
}
{
}
{
int ret;
return;
}
/* these point outside mmap now, next io_buffer_read_mmaped()
will fix them */
} else {
if (buf->buffer_size == 0)
if (ret <= 0)
break;
}
}
}
{
if (real_offset > OFF_T_MAX) {
return FALSE;
}
/* first reset everything */
/* then set the wanted position, next read will
pick up from there */
} else {
return FALSE;
}
return TRUE;
}
/* skip the first LF, if it exists */
{
return;
buf->cr_lookup_pos++;
}
}
{
/* FIXME: buf->offset isn't updated right.. (skip_lf thing?) */
unsigned char *ret_buf;
unsigned int i;
return NULL;
/* got it */
i++;
break;
}
}
buf->cr_lookup_pos = i;
return ret_buf;
}
{
*size = 0;
return NULL;
}
}
{
int ret;
ret = 1;
else {
/* we need more data */
*size = 0;
return ret;
}
}
return ret;
}
{
/* make sure we have enough space in buffer */
/* remove the unused bytes from beginning of buffer */
}
(buf->max_buffer_size == 0 ||
/* allocate more space */
}
return NULL;
}
{
int ret;
/* buffer is empty, try to send the data immediately */
if (ret < 0) {
/* disconnected */
return -1;
}
/* all sent */
return 1;
}
}
}
return 1;
}
{
return -2;
}
return 1;
}
{
}