istream-file.c revision 6449bd276af37b3e0b81a9c47ecd01f39a2cba53
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen/* Copyright (c) 2002-2003 Timo Sirainen */
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen/* @UNSAFE: whole file */
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "lib.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "alarm-hup.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "istream-internal.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "network.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include <time.h>
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include <unistd.h>
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include <sys/stat.h>
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#define I_STREAM_MIN_SIZE 4096
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#define STREAM_IS_BLOCKING(fstream) \
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen ((fstream)->timeout_msecs != 0)
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainenstruct file_istream {
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen struct _istream istream;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen size_t max_buffer_size;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen uoff_t skip_left;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen int timeout_msecs;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen void (*timeout_cb)(void *);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen void *timeout_context;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen unsigned int file:1;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen unsigned int autoclose_fd:1;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen};
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainenstatic void _close(struct _iostream *stream)
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen{
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen struct file_istream *fstream = (struct file_istream *) stream;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen struct _istream *_stream = (struct _istream *) stream;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen if (fstream->autoclose_fd && _stream->fd != -1) {
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen if (close(_stream->fd) < 0)
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen i_error("file_istream.close() failed: %m");
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen _stream->fd = -1;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen }
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen}
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainenstatic void _destroy(struct _iostream *stream)
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen{
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen struct _istream *_stream = (struct _istream *) stream;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen p_free(_stream->iostream.pool, _stream->w_buffer);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen}
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainenstatic void _set_max_buffer_size(struct _iostream *stream, size_t max_size)
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen{
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen struct file_istream *fstream = (struct file_istream *) stream;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen fstream->max_buffer_size = max_size;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen}
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainenstatic void _set_blocking(struct _iostream *stream, int timeout_msecs,
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen void (*timeout_cb)(void *), void *context)
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen{
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen struct file_istream *fstream = (struct file_istream *) stream;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen fstream->timeout_msecs = timeout_msecs;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen fstream->timeout_cb = timeout_cb;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen fstream->timeout_context = context;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen net_set_nonblock(fstream->istream.fd, timeout_msecs == 0);
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen if (timeout_msecs != 0)
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen alarm_hup_init();
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen}
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainenstatic void i_stream_grow_buffer(struct _istream *stream, size_t bytes)
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen{
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen struct file_istream *fstream = (struct file_istream *) stream;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen size_t old_size;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen old_size = stream->buffer_size;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen stream->buffer_size = stream->pos + bytes;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen if (stream->buffer_size <= I_STREAM_MIN_SIZE)
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen stream->buffer_size = I_STREAM_MIN_SIZE;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen else
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen stream->buffer_size = nearest_power(stream->buffer_size);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen if (fstream->max_buffer_size > 0 &&
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen stream->buffer_size > fstream->max_buffer_size)
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen stream->buffer_size = fstream->max_buffer_size;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen stream->buffer = stream->w_buffer =
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen p_realloc(stream->iostream.pool, stream->w_buffer,
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen old_size, stream->buffer_size);
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen}
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainenstatic void i_stream_compress(struct _istream *stream)
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen{
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen memmove(stream->w_buffer, stream->w_buffer + stream->skip,
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen stream->pos - stream->skip);
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen stream->pos -= stream->skip;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen stream->skip = 0;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen}
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainenstatic ssize_t _read(struct _istream *stream)
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen{
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen struct file_istream *fstream = (struct file_istream *) stream;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen time_t timeout_time;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen uoff_t read_limit;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen size_t size;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen ssize_t ret;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen if (stream->istream.closed)
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen return -1;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen stream->istream.stream_errno = 0;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen if (stream->pos == stream->buffer_size) {
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen if (stream->skip > 0) {
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen /* remove the unused bytes from beginning of buffer */
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen i_stream_compress(stream);
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen } else if (fstream->max_buffer_size == 0 ||
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen stream->buffer_size < fstream->max_buffer_size) {
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen /* buffer is full - grow it */
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen i_stream_grow_buffer(stream, I_STREAM_MIN_SIZE);
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen }
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen if (stream->pos == stream->buffer_size)
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen return -2; /* buffer full */
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen }
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen size = stream->buffer_size - stream->pos;
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen if (stream->istream.v_limit > 0) {
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen i_assert(stream->istream.v_limit >= stream->istream.v_offset);
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen read_limit = stream->istream.v_limit -
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen stream->istream.v_offset + fstream->skip_left;
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen if (read_limit <= stream->pos - stream->skip) {
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen /* virtual limit reached == EOF */
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen stream->istream.eof = TRUE;
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen return -1;
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen }
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen read_limit -= stream->pos - stream->skip;
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen if (size > read_limit)
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen size = read_limit;
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen }
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen timeout_time = GET_TIMEOUT_TIME(fstream);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen ret = -1;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen do {
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen if (ret == 0 && timeout_time > 0 && time(NULL) > timeout_time) {
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen /* timeouted */
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen if (fstream->timeout_cb != NULL)
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen fstream->timeout_cb(fstream->timeout_context);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen stream->istream.stream_errno = EAGAIN;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen return -1;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen }
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen if (fstream->file) {
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen ret = pread(stream->fd,
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen stream->w_buffer + stream->pos, size,
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen stream->istream.start_offset +
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen stream->istream.v_offset +
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen (stream->pos - stream->skip));
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen } else {
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen ret = read(stream->fd,
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen stream->w_buffer + stream->pos, size);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen }
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen if (ret == 0) {
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen /* EOF */
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen stream->istream.stream_errno = 0;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen stream->istream.eof = TRUE;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen return -1;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen }
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen if (ret < 0) {
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen if (errno == ECONNRESET || errno == ETIMEDOUT) {
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen /* treat as disconnection */
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen stream->istream.stream_errno = 0;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen stream->istream.eof = TRUE;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen return -1;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen }
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen if (errno == EINTR || errno == EAGAIN)
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen ret = 0;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen else {
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen stream->istream.stream_errno = errno;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen return -1;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen }
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen }
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen if (ret > 0 && fstream->skip_left > 0) {
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen i_assert(!fstream->file);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen if (fstream->skip_left >= (size_t)ret) {
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen fstream->skip_left -= ret;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen ret = 0;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen } else {
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen ret -= fstream->skip_left;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen stream->pos += fstream->skip_left;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen stream->skip += fstream->skip_left;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen fstream->skip_left = 0;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen }
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen }
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen } while (ret == 0 && STREAM_IS_BLOCKING(fstream));
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen stream->pos += ret;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen return ret;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen}
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainenstatic void _skip(struct _istream *stream, uoff_t count)
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen{
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen struct file_istream *fstream = (struct file_istream *) stream;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen i_assert(stream->skip == stream->pos);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen if (!fstream->file)
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen fstream->skip_left += count;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen stream->istream.v_offset += count;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen stream->skip = stream->pos = 0;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen}
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainenstatic void _seek(struct _istream *stream, uoff_t v_offset)
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen{
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen struct file_istream *fstream = (struct file_istream *) stream;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen if (!fstream->file) {
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen stream->istream.stream_errno = ESPIPE;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen return;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen }
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen stream->istream.stream_errno = 0;
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen stream->istream.v_offset = v_offset;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen stream->skip = stream->pos = 0;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen}
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainenstruct istream *i_stream_create_file(int fd, pool_t pool,
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen size_t max_buffer_size, int autoclose_fd)
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen{
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen struct file_istream *fstream;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen struct stat st;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen fstream = p_new(pool, struct file_istream, 1);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen fstream->max_buffer_size = max_buffer_size;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen fstream->autoclose_fd = autoclose_fd;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen fstream->istream.iostream.close = _close;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen fstream->istream.iostream.destroy = _destroy;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen fstream->istream.iostream.set_max_buffer_size = _set_max_buffer_size;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen fstream->istream.iostream.set_blocking = _set_blocking;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen fstream->istream.read = _read;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen fstream->istream.skip_count = _skip;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen fstream->istream.seek = _seek;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen /* get size of fd if it's a file */
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen if (fstat(fd, &st) == 0 && S_ISREG(st.st_mode))
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen fstream->file = TRUE;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen return _i_stream_create(&fstream->istream, pool, fd, 0, 0);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen}
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen