ostream-file.c revision 6adf683655750bcb809275cd65dc75fd12214198
76b43e4417bab52e913da39b5f5bc2a130d3f149Timo Sirainen/* Copyright (c) 2002-2016 Dovecot authors, see the included COPYING file */
f67e08c0dbd9c0441e818d07a0b40b897f907495Timo Sirainen/* @UNSAFE: whole file */
1d5e52e398381873081455ad99edec945038eec0Timo Sirainen/* try to keep the buffer size within 4k..128k. ReiserFS may actually return
1d5e52e398381873081455ad99edec945038eec0Timo Sirainen 128k as optimal size. */
1d5e52e398381873081455ad99edec945038eec0Timo Sirainen#define DEFAULT_OPTIMAL_BLOCK_SIZE IO_BLOCK_SIZE
1d5e52e398381873081455ad99edec945038eec0Timo Sirainen ((fstream)->head == (fstream)->tail && !(fstream)->full)
1d5e52e398381873081455ad99edec945038eec0Timo Sirainen ((size) < SSIZE_T_MAX ? (size_t)(size) : SSIZE_T_MAX)
1d5e52e398381873081455ad99edec945038eec0Timo Sirainenstatic void stream_send_io(struct file_ostream *fstream);
1d5e52e398381873081455ad99edec945038eec0Timo Sirainenstatic void stream_closed(struct file_ostream *fstream)
1d5e52e398381873081455ad99edec945038eec0Timo Sirainen if (fstream->autoclose_fd && fstream->fd != -1) {
1d5e52e398381873081455ad99edec945038eec0Timo Sirainen o_stream_get_name(&fstream->ostream.ostream));
1d5e52e398381873081455ad99edec945038eec0Timo Sirainenvoid o_stream_file_close(struct iostream_private *stream,
1d5e52e398381873081455ad99edec945038eec0Timo Sirainen struct file_ostream *fstream = (struct file_ostream *)stream;
1d5e52e398381873081455ad99edec945038eec0Timo Sirainen /* flush output before really closing it */
1d5e52e398381873081455ad99edec945038eec0Timo Sirainen (void)o_stream_flush(&fstream->ostream.ostream);
1d5e52e398381873081455ad99edec945038eec0Timo Sirainenstatic void o_stream_file_destroy(struct iostream_private *stream)
1d5e52e398381873081455ad99edec945038eec0Timo Sirainen struct file_ostream *fstream = (struct file_ostream *)stream;
1d5e52e398381873081455ad99edec945038eec0Timo Sirainenstatic size_t file_buffer_get_used_size(struct file_ostream *fstream)
1d5e52e398381873081455ad99edec945038eec0Timo Sirainen return fstream->full ? fstream->buffer_size : 0;
1d5e52e398381873081455ad99edec945038eec0Timo Sirainen /* ...HXXXT... */
1d5e52e398381873081455ad99edec945038eec0Timo Sirainenstatic void update_buffer(struct file_ostream *fstream, size_t size)
1d5e52e398381873081455ad99edec945038eec0Timo Sirainen /* ...HXXXT... */
1d5e52e398381873081455ad99edec945038eec0Timo Sirainenstatic void o_stream_socket_cork(struct file_ostream *fstream)
1d5e52e398381873081455ad99edec945038eec0Timo Sirainen if (fstream->ostream.corked && !fstream->socket_cork_set) {
1d5e52e398381873081455ad99edec945038eec0Timo Sirainenstatic int o_stream_lseek(struct file_ostream *fstream)
1d5e52e398381873081455ad99edec945038eec0Timo Sirainen if (fstream->real_offset == fstream->buffer_offset)
1d5e52e398381873081455ad99edec945038eec0Timo Sirainen ret = lseek(fstream->fd, (off_t)fstream->buffer_offset, SEEK_SET);
1d5e52e398381873081455ad99edec945038eec0Timo Sirainen io_stream_set_error(&fstream->ostream.iostream,
1d5e52e398381873081455ad99edec945038eec0Timo Sirainen "lseek() failed: %m");
1d5e52e398381873081455ad99edec945038eec0Timo Sirainen fstream->ostream.ostream.stream_errno = errno;
1d5e52e398381873081455ad99edec945038eec0Timo Sirainen io_stream_set_error(&fstream->ostream.iostream,
1d5e52e398381873081455ad99edec945038eec0Timo Sirainen "lseek() returned wrong value");
1d5e52e398381873081455ad99edec945038eec0Timo Sirainen fstream->ostream.ostream.stream_errno = EINVAL;
1d5e52e398381873081455ad99edec945038eec0Timo Sirainen fstream->real_offset = fstream->buffer_offset;
1d5e52e398381873081455ad99edec945038eec0Timo Sirainenssize_t o_stream_file_writev(struct file_ostream *fstream,
1d5e52e398381873081455ad99edec945038eec0Timo Sirainen unsigned int i;
1d5e52e398381873081455ad99edec945038eec0Timo Sirainen fstream->real_offset == fstream->buffer_offset) {
1d5e52e398381873081455ad99edec945038eec0Timo Sirainen ret = write(fstream->fd, iov->iov_base, iov->iov_len);
1d5e52e398381873081455ad99edec945038eec0Timo Sirainen ret = pwrite(fstream->fd, iov->iov_base, iov->iov_len,
sent = 0;
size = 0;
for (i = 0; i < IOV_MAX; i++)
IOV_MAX);
size = 0;
for (i = 0; i < iov_count; i++)
if (ret > 0) {
return ret;
static ssize_t
unsigned int iov_count)
bool partial;
if (ret < 0) {
iov++;
iov_count--;
if (size == 0)
if (ret2 > 0) {
if (ret2 < 0)
return ret;
int iov_len;
if (iov_len > 0) {
if (ret < 0)
int ret;
else if (!set) {
/* XXXT...HXXX */
int ret;
if (ret == 0)
sent = 0;
fstream);
return sent;
unsigned int iov_count)
if (ret < 0)
iov++;
iov_count--;
if (iov_count == 0)
return ret;
iov++;
iov_count--;
for (i = 0; i < iov_count; i++) {
return ret;
static size_t
/* XXXT...HXXX */
return size;
if (used > 0 &&
skip = 0;
if (left > 0) {
if (skip > 0) {
} else if (skip == 0) {
bool *sendfile_not_supported_r)
if (ret == 0) {
return ret;
if (ret <= 0) {
if (ret == 0)
ret = 0;
const unsigned char *data;
read_size) == 0)
i_unreached();
if (ret < 0) {
if (ret == 0) {
if (ret == 0) {
bool same_stream;
bool sendfile_not_supported;
return ret;
if (!same_stream)
struct ostream *
if (max_buffer_size == 0)
return ostream;
struct ostream *
if (offset >= 0) {
return ostream;
struct ostream *
return output;
struct ostream *
return ostream;
return output;