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