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