istream-file.c revision 07e4875d250e7a7157cd99132aafc773cf3cdf83
5e0ce63bb65db34d7f48b34bbb5545fa791781c4Timo Sirainen/* Copyright (c) 2002-2003 Timo Sirainen */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
5254d77805cd35b9356d072ba325c356c43b0d51Timo Sirainen/* @UNSAFE: whole file */
5254d77805cd35b9356d072ba325c356c43b0d51Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen#include "lib.h"
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen#include "ioloop.h"
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen#include "istream-internal.h"
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen#include "network.h"
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen#include <time.h>
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen#include <unistd.h>
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen#include <sys/stat.h>
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen#define I_STREAM_MIN_SIZE 4096
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainenstruct file_istream {
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen struct _istream istream;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen struct timeval fstat_cache_stamp;
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen size_t max_buffer_size;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen uoff_t skip_left;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen unsigned int file:1;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen unsigned int autoclose_fd:1;
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen};
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainenstatic void _close(struct _iostream *stream)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen{
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen struct file_istream *fstream = (struct file_istream *) stream;
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen struct _istream *_stream = (struct _istream *) stream;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (fstream->autoclose_fd && _stream->fd != -1) {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (close(_stream->fd) < 0)
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen i_error("file_istream.close() failed: %m");
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen _stream->fd = -1;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen }
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen}
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainenstatic void _destroy(struct _iostream *stream)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen{
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen struct _istream *_stream = (struct _istream *) stream;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen p_free(_stream->iostream.pool, _stream->w_buffer);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen}
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainenstatic void _set_max_buffer_size(struct _iostream *stream, size_t max_size)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen{
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen struct file_istream *fstream = (struct file_istream *) stream;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen fstream->max_buffer_size = max_size;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen}
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainenstatic void i_stream_grow_buffer(struct _istream *stream, size_t bytes)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen{
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen struct file_istream *fstream = (struct file_istream *) stream;
01af88dfbb7a022ddb3ab9fb4159f2a4a204ead3Timo Sirainen size_t old_size;
01af88dfbb7a022ddb3ab9fb4159f2a4a204ead3Timo Sirainen
01af88dfbb7a022ddb3ab9fb4159f2a4a204ead3Timo Sirainen old_size = stream->buffer_size;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen stream->buffer_size = stream->pos + bytes;
01af88dfbb7a022ddb3ab9fb4159f2a4a204ead3Timo Sirainen if (stream->buffer_size <= I_STREAM_MIN_SIZE)
01af88dfbb7a022ddb3ab9fb4159f2a4a204ead3Timo Sirainen stream->buffer_size = I_STREAM_MIN_SIZE;
3bbe99d30871f49610aac0417ee5951d1e740b98Timo Sirainen else {
3bbe99d30871f49610aac0417ee5951d1e740b98Timo Sirainen stream->buffer_size =
3bbe99d30871f49610aac0417ee5951d1e740b98Timo Sirainen pool_get_exp_grown_size(stream->iostream.pool,
3bbe99d30871f49610aac0417ee5951d1e740b98Timo Sirainen old_size, stream->buffer_size);
3bbe99d30871f49610aac0417ee5951d1e740b98Timo Sirainen }
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (fstream->max_buffer_size > 0 &&
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen stream->buffer_size > fstream->max_buffer_size)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen stream->buffer_size = fstream->max_buffer_size;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen stream->buffer = stream->w_buffer =
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen p_realloc(stream->iostream.pool, stream->w_buffer,
01af88dfbb7a022ddb3ab9fb4159f2a4a204ead3Timo Sirainen old_size, stream->buffer_size);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen}
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainenstatic void i_stream_compress(struct _istream *stream)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen{
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen memmove(stream->w_buffer, stream->w_buffer + stream->skip,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen stream->pos - stream->skip);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen stream->pos -= stream->skip;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen stream->skip = 0;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen}
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainenstatic ssize_t _read(struct _istream *stream)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen{
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen struct file_istream *fstream = (struct file_istream *) stream;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen size_t size;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen ssize_t ret;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (stream->istream.closed)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen return -1;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen stream->istream.stream_errno = 0;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (stream->pos == stream->buffer_size) {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (stream->skip > 0) {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen /* remove the unused bytes from beginning of buffer */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen i_stream_compress(stream);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen } else if (fstream->max_buffer_size == 0 ||
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen stream->buffer_size < fstream->max_buffer_size) {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen /* buffer is full - grow it */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen i_stream_grow_buffer(stream, I_STREAM_MIN_SIZE);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen }
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (stream->pos == stream->buffer_size)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen return -2; /* buffer full */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen }
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen size = stream->buffer_size - stream->pos;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen ret = -1;
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen if (fstream->file) {
1060afdc2fcdf647dbb3bc11647401f1b44a3a8aTimo Sirainen do {
1060afdc2fcdf647dbb3bc11647401f1b44a3a8aTimo Sirainen ret = pread(stream->fd, stream->w_buffer + stream->pos,
1060afdc2fcdf647dbb3bc11647401f1b44a3a8aTimo Sirainen size, stream->istream.v_offset +
1060afdc2fcdf647dbb3bc11647401f1b44a3a8aTimo Sirainen (stream->pos - stream->skip));
1060afdc2fcdf647dbb3bc11647401f1b44a3a8aTimo Sirainen } while (ret < 0 && errno == EINTR);
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen } else {
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen ret = read(stream->fd, stream->w_buffer + stream->pos, size);
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen }
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen if (ret == 0) {
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen /* EOF */
9e095dd6a77097356aca8216356d4d71ef1bea45Timo Sirainen stream->istream.eof = TRUE;
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen return -1;
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen }
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen if (ret < 0) {
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen if (errno == EINTR || errno == EAGAIN)
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen ret = 0;
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen else {
9e095dd6a77097356aca8216356d4d71ef1bea45Timo Sirainen stream->istream.eof = TRUE;
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen stream->istream.stream_errno = errno;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen return -1;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen }
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen }
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen if (ret > 0 && fstream->skip_left > 0) {
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen i_assert(!fstream->file);
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen i_assert(stream->skip == stream->pos);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen if (fstream->skip_left >= (size_t)ret) {
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen fstream->skip_left -= ret;
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen ret = 0;
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen } else {
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen ret -= fstream->skip_left;
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen stream->pos += fstream->skip_left;
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen stream->skip += fstream->skip_left;
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen fstream->skip_left = 0;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen }
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen }
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen stream->pos += ret;
1060afdc2fcdf647dbb3bc11647401f1b44a3a8aTimo Sirainen i_assert(ret != 0 || !fstream->file);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen return ret;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen}
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainenstatic void _seek(struct _istream *stream, uoff_t v_offset)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen{
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen struct file_istream *fstream = (struct file_istream *) stream;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
411d6baa37f31d90730e90c4a28c43e1974bbe58Timo Sirainen if (!stream->istream.seekable) {
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen if (v_offset < stream->istream.v_offset) {
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen stream->istream.stream_errno = ESPIPE;
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen return;
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen }
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen fstream->skip_left += v_offset - stream->istream.v_offset;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen }
143cb2e0744e647f8fc637bbdea1106c1587a4bfTimo Sirainen
143cb2e0744e647f8fc637bbdea1106c1587a4bfTimo Sirainen stream->istream.stream_errno = 0;
143cb2e0744e647f8fc637bbdea1106c1587a4bfTimo Sirainen stream->istream.v_offset = v_offset;
143cb2e0744e647f8fc637bbdea1106c1587a4bfTimo Sirainen stream->skip = stream->pos = 0;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen}
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainenstatic void _sync(struct _istream *stream)
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen{
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen struct file_istream *fstream = (struct file_istream *) stream;
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen fstream->fstat_cache_stamp.tv_sec = 0;
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen if (!stream->istream.seekable) {
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen /* can't do anything or data would be lost */
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen return;
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen }
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen stream->skip = stream->pos = 0;
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen}
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainenstatic int fstat_cached(struct file_istream *fstream)
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen{
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen if (fstream->fstat_cache_stamp.tv_sec == ioloop_timeval.tv_sec &&
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen fstream->fstat_cache_stamp.tv_usec == ioloop_timeval.tv_usec)
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen return 0;
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen if (fstat(fstream->istream.fd, &fstream->istream.statbuf) < 0) {
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen i_error("file_istream.fstat() failed: %m");
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen return -1;
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen }
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen fstream->fstat_cache_stamp = ioloop_timeval;
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen return 0;
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen}
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainenstatic const struct stat *_stat(struct _istream *stream)
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen{
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen struct file_istream *fstream = (struct file_istream *) stream;
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen if (fstream->file) {
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen if (fstat_cached(fstream) < 0)
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen return NULL;
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen }
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen return &stream->statbuf;
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen}
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainenstruct istream *i_stream_create_file(int fd, pool_t pool,
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen size_t max_buffer_size, int autoclose_fd)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen{
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen struct file_istream *fstream;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen struct stat st;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen fstream = p_new(pool, struct file_istream, 1);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen fstream->max_buffer_size = max_buffer_size;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen fstream->autoclose_fd = autoclose_fd;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen fstream->istream.iostream.close = _close;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen fstream->istream.iostream.destroy = _destroy;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen fstream->istream.iostream.set_max_buffer_size = _set_max_buffer_size;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen fstream->istream.read = _read;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen fstream->istream.seek = _seek;
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen fstream->istream.sync = _sync;
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen fstream->istream.stat = _stat;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen /* get size of fd if it's a file */
411d6baa37f31d90730e90c4a28c43e1974bbe58Timo Sirainen if (fstat(fd, &st) == 0 && S_ISREG(st.st_mode)) {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen fstream->file = TRUE;
411d6baa37f31d90730e90c4a28c43e1974bbe58Timo Sirainen fstream->istream.istream.seekable = TRUE;
411d6baa37f31d90730e90c4a28c43e1974bbe58Timo Sirainen }
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen return _i_stream_create(&fstream->istream, pool, fd, 0);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen}