istream-mmap.c revision 252db51b6c0a605163326b3ea5d09e9936ca3b29
bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2002-2003 Timo Sirainen */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen#include "lib.h"
c6227d7ecc972b6c58602d78602210f75190ae3fTimo Sirainen#include "ioloop.h"
bca919b207e27d0d08b431bdb0f2ac099ef8b512Timo Sirainen#include "mmap-util.h"
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen#include "istream-internal.h"
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen
7a7d2aa11e46195e2d92d6c337d7e78052a5ce67Timo Sirainen#include <unistd.h>
a956137aa86d16e5a90b9d4a9e69d3854d824380Timo Sirainen#include <sys/stat.h>
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenstruct mmap_istream {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct istream_private istream;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct timeval fstat_cache_stamp;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
2b9e49e4e65e3e2dca38f56971029a3051ccdb99Timo Sirainen void *mmap_base;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen off_t mmap_offset;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen uoff_t v_size;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen unsigned int autoclose_fd:1;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen};
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenstatic size_t mmap_pagemask = 0;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
2b9e49e4e65e3e2dca38f56971029a3051ccdb99Timo Sirainenstatic void _close(struct iostream_private *stream)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen{
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct mmap_istream *mstream = (struct mmap_istream *) stream;
afa201e7e1d2447e8dfa1aff43de0fdad564105fTimo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (mstream->autoclose_fd && mstream->istream.fd != -1) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (close(mstream->istream.fd) < 0)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen i_error("mmap_istream.close() failed: %m");
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen }
c6227d7ecc972b6c58602d78602210f75190ae3fTimo Sirainen mstream->istream.fd = -1;
c6227d7ecc972b6c58602d78602210f75190ae3fTimo Sirainen}
c6227d7ecc972b6c58602d78602210f75190ae3fTimo Sirainen
c6227d7ecc972b6c58602d78602210f75190ae3fTimo Sirainenstatic void i_stream_munmap(struct mmap_istream *mstream)
804fa3f03bd9170272168a5ad214053bbe3160c7Josef 'Jeff' Sipek{
c6227d7ecc972b6c58602d78602210f75190ae3fTimo Sirainen struct istream_private *_stream = &mstream->istream;
c6227d7ecc972b6c58602d78602210f75190ae3fTimo Sirainen
c6227d7ecc972b6c58602d78602210f75190ae3fTimo Sirainen if (_stream->buffer != NULL) {
c6227d7ecc972b6c58602d78602210f75190ae3fTimo Sirainen if (munmap(mstream->mmap_base, _stream->buffer_size) < 0)
c6227d7ecc972b6c58602d78602210f75190ae3fTimo Sirainen i_error("mmap_istream.munmap() failed: %m");
c6227d7ecc972b6c58602d78602210f75190ae3fTimo Sirainen mstream->mmap_base = NULL;
c6227d7ecc972b6c58602d78602210f75190ae3fTimo Sirainen _stream->buffer = NULL;
c6227d7ecc972b6c58602d78602210f75190ae3fTimo Sirainen _stream->buffer_size = 0;
c6227d7ecc972b6c58602d78602210f75190ae3fTimo Sirainen mstream->mmap_offset = 0;
c6227d7ecc972b6c58602d78602210f75190ae3fTimo Sirainen }
c6227d7ecc972b6c58602d78602210f75190ae3fTimo Sirainen}
c6227d7ecc972b6c58602d78602210f75190ae3fTimo Sirainen
c6227d7ecc972b6c58602d78602210f75190ae3fTimo Sirainenstatic void _destroy(struct iostream_private *stream)
c6227d7ecc972b6c58602d78602210f75190ae3fTimo Sirainen{
c6227d7ecc972b6c58602d78602210f75190ae3fTimo Sirainen struct mmap_istream *mstream = (struct mmap_istream *) stream;
c6227d7ecc972b6c58602d78602210f75190ae3fTimo Sirainen
eadbca0f2b78fcc36332678fee9ee08003df63deTimo Sirainen i_stream_munmap(mstream);
eadbca0f2b78fcc36332678fee9ee08003df63deTimo Sirainen}
eadbca0f2b78fcc36332678fee9ee08003df63deTimo Sirainen
eadbca0f2b78fcc36332678fee9ee08003df63deTimo Sirainenstatic size_t mstream_get_mmap_block_size(struct istream_private *stream)
eadbca0f2b78fcc36332678fee9ee08003df63deTimo Sirainen{
eadbca0f2b78fcc36332678fee9ee08003df63deTimo Sirainen return (stream->max_buffer_size + mmap_get_page_size() - 1) & ~
860e6dd603921f61b0cd53c1cc16e1d66d312699Timo Sirainen (mmap_get_page_size() - 1);
860e6dd603921f61b0cd53c1cc16e1d66d312699Timo Sirainen}
eadbca0f2b78fcc36332678fee9ee08003df63deTimo Sirainen
eadbca0f2b78fcc36332678fee9ee08003df63deTimo Sirainenstatic ssize_t _read(struct istream_private *stream)
eadbca0f2b78fcc36332678fee9ee08003df63deTimo Sirainen{
eadbca0f2b78fcc36332678fee9ee08003df63deTimo Sirainen struct mmap_istream *mstream = (struct mmap_istream *) stream;
eadbca0f2b78fcc36332678fee9ee08003df63deTimo Sirainen size_t aligned_skip;
eadbca0f2b78fcc36332678fee9ee08003df63deTimo Sirainen uoff_t top;
eadbca0f2b78fcc36332678fee9ee08003df63deTimo Sirainen
eadbca0f2b78fcc36332678fee9ee08003df63deTimo Sirainen stream->istream.stream_errno = 0;
eadbca0f2b78fcc36332678fee9ee08003df63deTimo Sirainen
eadbca0f2b78fcc36332678fee9ee08003df63deTimo Sirainen if (stream->pos < stream->buffer_size) {
eadbca0f2b78fcc36332678fee9ee08003df63deTimo Sirainen /* more bytes available without needing to mmap() */
eadbca0f2b78fcc36332678fee9ee08003df63deTimo Sirainen stream->pos = stream->buffer_size;
eadbca0f2b78fcc36332678fee9ee08003df63deTimo Sirainen return stream->pos - stream->skip;
eadbca0f2b78fcc36332678fee9ee08003df63deTimo Sirainen }
eadbca0f2b78fcc36332678fee9ee08003df63deTimo Sirainen
eadbca0f2b78fcc36332678fee9ee08003df63deTimo Sirainen if (stream->istream.v_offset >= mstream->v_size) {
eadbca0f2b78fcc36332678fee9ee08003df63deTimo Sirainen stream->istream.eof = TRUE;
eadbca0f2b78fcc36332678fee9ee08003df63deTimo Sirainen return -1;
eadbca0f2b78fcc36332678fee9ee08003df63deTimo Sirainen }
eadbca0f2b78fcc36332678fee9ee08003df63deTimo Sirainen
eadbca0f2b78fcc36332678fee9ee08003df63deTimo Sirainen aligned_skip = stream->skip & ~mmap_pagemask;
eadbca0f2b78fcc36332678fee9ee08003df63deTimo Sirainen if (aligned_skip == 0 && mstream->mmap_base != NULL) {
eadbca0f2b78fcc36332678fee9ee08003df63deTimo Sirainen /* didn't skip enough bytes */
eadbca0f2b78fcc36332678fee9ee08003df63deTimo Sirainen return -2;
eadbca0f2b78fcc36332678fee9ee08003df63deTimo Sirainen }
eadbca0f2b78fcc36332678fee9ee08003df63deTimo Sirainen
eadbca0f2b78fcc36332678fee9ee08003df63deTimo Sirainen stream->skip -= aligned_skip;
eadbca0f2b78fcc36332678fee9ee08003df63deTimo Sirainen mstream->mmap_offset += aligned_skip;
eadbca0f2b78fcc36332678fee9ee08003df63deTimo Sirainen
eadbca0f2b78fcc36332678fee9ee08003df63deTimo Sirainen if (mstream->mmap_base != NULL) {
eadbca0f2b78fcc36332678fee9ee08003df63deTimo Sirainen if (munmap(mstream->mmap_base, stream->buffer_size) < 0)
eadbca0f2b78fcc36332678fee9ee08003df63deTimo Sirainen i_error("io_stream_read_mmaped(): munmap() failed: %m");
eadbca0f2b78fcc36332678fee9ee08003df63deTimo Sirainen }
eadbca0f2b78fcc36332678fee9ee08003df63deTimo Sirainen
eadbca0f2b78fcc36332678fee9ee08003df63deTimo Sirainen top = mstream->v_size - mstream->mmap_offset;
eadbca0f2b78fcc36332678fee9ee08003df63deTimo Sirainen stream->buffer_size = I_MIN(top, mstream_get_mmap_block_size(stream));
eadbca0f2b78fcc36332678fee9ee08003df63deTimo Sirainen
eadbca0f2b78fcc36332678fee9ee08003df63deTimo Sirainen i_assert((uoff_t)mstream->mmap_offset + stream->buffer_size <=
eadbca0f2b78fcc36332678fee9ee08003df63deTimo Sirainen mstream->v_size);
eadbca0f2b78fcc36332678fee9ee08003df63deTimo Sirainen
eadbca0f2b78fcc36332678fee9ee08003df63deTimo Sirainen if (stream->buffer_size == 0) {
eadbca0f2b78fcc36332678fee9ee08003df63deTimo Sirainen /* don't bother even trying mmap */
eadbca0f2b78fcc36332678fee9ee08003df63deTimo Sirainen mstream->mmap_base = NULL;
eadbca0f2b78fcc36332678fee9ee08003df63deTimo Sirainen stream->buffer = NULL;
eadbca0f2b78fcc36332678fee9ee08003df63deTimo Sirainen } else {
eadbca0f2b78fcc36332678fee9ee08003df63deTimo Sirainen mstream->mmap_base =
eadbca0f2b78fcc36332678fee9ee08003df63deTimo Sirainen mmap(NULL, stream->buffer_size, PROT_READ, MAP_PRIVATE,
eadbca0f2b78fcc36332678fee9ee08003df63deTimo Sirainen stream->fd, mstream->mmap_offset);
eadbca0f2b78fcc36332678fee9ee08003df63deTimo Sirainen if (mstream->mmap_base == MAP_FAILED) {
eadbca0f2b78fcc36332678fee9ee08003df63deTimo Sirainen stream->istream.stream_errno = errno;
e5fd6dfd0a492e4708d4dbb7971d7fc5d7b8fd85Timo Sirainen mstream->mmap_base = NULL;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen stream->buffer = NULL;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen stream->buffer_size = 0;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen stream->skip = stream->pos = 0;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen i_error("mmap_istream.mmap() failed: %m");
d22301419109ed4a38351715e6760011421dadecTimo Sirainen return -1;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen }
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen stream->buffer = mstream->mmap_base;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen }
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (stream->buffer_size > mmap_get_page_size()) {
2b9e49e4e65e3e2dca38f56971029a3051ccdb99Timo Sirainen if (madvise(mstream->mmap_base, stream->buffer_size,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen MADV_SEQUENTIAL) < 0)
d22301419109ed4a38351715e6760011421dadecTimo Sirainen i_error("mmap_istream.madvise(): %m");
d22301419109ed4a38351715e6760011421dadecTimo Sirainen }
d22301419109ed4a38351715e6760011421dadecTimo Sirainen
d22301419109ed4a38351715e6760011421dadecTimo Sirainen stream->pos = stream->buffer_size;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen i_assert(stream->pos - stream->skip != 0);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return stream->pos - stream->skip;
8c909e451d14075c05d90382cf8eebc4e354f569Timo Sirainen}
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
d22301419109ed4a38351715e6760011421dadecTimo Sirainenstatic void _seek(struct istream_private *stream, uoff_t v_offset,
d22301419109ed4a38351715e6760011421dadecTimo Sirainen bool mark ATTR_UNUSED)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen{
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct mmap_istream *mstream = (struct mmap_istream *) stream;
df3963075d67f76ade66b6a74764f4eae31d9c87Josef 'Jeff' Sipek
d22301419109ed4a38351715e6760011421dadecTimo Sirainen if (stream->buffer_size != 0 &&
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen (uoff_t)mstream->mmap_offset <= v_offset &&
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen (uoff_t)mstream->mmap_offset + stream->buffer_size > v_offset) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* already mmaped */
9865d9e7c5713e41db939222ed9c0225a11fb99eTimo Sirainen stream->skip = stream->pos = v_offset - mstream->mmap_offset;
9865d9e7c5713e41db939222ed9c0225a11fb99eTimo Sirainen } else {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* force reading next time */
e5fb952c6d49d3b6bff1746551566202e92947daTimo Sirainen i_stream_munmap(mstream);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen stream->skip = stream->pos = v_offset;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen }
6b8043a4d96d696a6b65ebe9ae4f56fbec638348Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen stream->istream.v_offset = v_offset;
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen}
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen
e5fb952c6d49d3b6bff1746551566202e92947daTimo Sirainenstatic void _sync(struct istream_private *stream)
e5fb952c6d49d3b6bff1746551566202e92947daTimo Sirainen{
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct mmap_istream *mstream = (struct mmap_istream *) stream;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
7baab0b0b60df7ce9093d0881cd322dff1e79491Timo Sirainen i_stream_munmap(mstream);
4b2a4c8c762e3eaddf7fd2abfe7d4cca6e5e3fd8Timo Sirainen stream->skip = stream->pos = stream->istream.v_offset;
d4002fe1f64d25a792f76fb102ef7dc519cd4e24Martti Rannanjärvi
d4002fe1f64d25a792f76fb102ef7dc519cd4e24Martti Rannanjärvi mstream->fstat_cache_stamp.tv_sec = 0;
4b2a4c8c762e3eaddf7fd2abfe7d4cca6e5e3fd8Timo Sirainen}
e5fb952c6d49d3b6bff1746551566202e92947daTimo Sirainen
e5fb952c6d49d3b6bff1746551566202e92947daTimo Sirainenstatic int fstat_cached(struct mmap_istream *mstream)
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch{
e5fb952c6d49d3b6bff1746551566202e92947daTimo Sirainen if (mstream->fstat_cache_stamp.tv_sec == ioloop_timeval.tv_sec &&
607a8bc27298b711270381364f2a9a999a810a87Timo Sirainen mstream->fstat_cache_stamp.tv_usec == ioloop_timeval.tv_usec)
607a8bc27298b711270381364f2a9a999a810a87Timo Sirainen return 0;
607a8bc27298b711270381364f2a9a999a810a87Timo Sirainen
607a8bc27298b711270381364f2a9a999a810a87Timo Sirainen if (fstat(mstream->istream.fd, &mstream->istream.statbuf) < 0) {
607a8bc27298b711270381364f2a9a999a810a87Timo Sirainen i_error("mmap_istream.fstat() failed: %m");
607a8bc27298b711270381364f2a9a999a810a87Timo Sirainen return -1;
607a8bc27298b711270381364f2a9a999a810a87Timo Sirainen }
607a8bc27298b711270381364f2a9a999a810a87Timo Sirainen
607a8bc27298b711270381364f2a9a999a810a87Timo Sirainen mstream->fstat_cache_stamp = ioloop_timeval;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return 0;
e5fb952c6d49d3b6bff1746551566202e92947daTimo Sirainen}
9865d9e7c5713e41db939222ed9c0225a11fb99eTimo Sirainen
e5fb952c6d49d3b6bff1746551566202e92947daTimo Sirainenstatic const struct stat *
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen_stat(struct istream_private *stream, bool exact ATTR_UNUSED)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen{
607a8bc27298b711270381364f2a9a999a810a87Timo Sirainen struct mmap_istream *mstream = (struct mmap_istream *) stream;
607a8bc27298b711270381364f2a9a999a810a87Timo Sirainen
607a8bc27298b711270381364f2a9a999a810a87Timo Sirainen if (fstat_cached(mstream) < 0)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return NULL;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
9865d9e7c5713e41db939222ed9c0225a11fb99eTimo Sirainen return &stream->statbuf;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen}
1127f3e1ad7135b6ee5d5e13f8fd1e72f85a76f8Timo Sirainen
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Boschstruct istream *i_stream_create_mmap(int fd, size_t block_size,
1127f3e1ad7135b6ee5d5e13f8fd1e72f85a76f8Timo Sirainen uoff_t start_offset, uoff_t v_size,
1127f3e1ad7135b6ee5d5e13f8fd1e72f85a76f8Timo Sirainen bool autoclose_fd)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen{
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct mmap_istream *mstream;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct istream *istream;
de62ce819d59a529530da4b57be1b8d6dad13d6bTimo Sirainen struct stat st;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (mmap_pagemask == 0)
de62ce819d59a529530da4b57be1b8d6dad13d6bTimo Sirainen mmap_pagemask = mmap_get_page_size()-1;
de62ce819d59a529530da4b57be1b8d6dad13d6bTimo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (v_size == 0) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (fstat(fd, &st) < 0)
9865d9e7c5713e41db939222ed9c0225a11fb99eTimo Sirainen i_error("i_stream_create_mmap(): fstat() failed: %m");
9865d9e7c5713e41db939222ed9c0225a11fb99eTimo Sirainen else {
9865d9e7c5713e41db939222ed9c0225a11fb99eTimo Sirainen v_size = st.st_size;
9865d9e7c5713e41db939222ed9c0225a11fb99eTimo Sirainen if (start_offset > v_size)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen start_offset = v_size;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen v_size -= start_offset;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen }
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen }
7e1b549a1d841e59faad16430cbd1d56317db8afTimo Sirainen
7e1b549a1d841e59faad16430cbd1d56317db8afTimo Sirainen mstream = i_new(struct mmap_istream, 1);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mstream->autoclose_fd = autoclose_fd;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mstream->v_size = v_size;
f605df8a4c15cc7a11e16fdde994d51473700890Timo Sirainen
f605df8a4c15cc7a11e16fdde994d51473700890Timo Sirainen mstream->istream.iostream.close = _close;
f605df8a4c15cc7a11e16fdde994d51473700890Timo Sirainen mstream->istream.iostream.destroy = _destroy;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
df3963075d67f76ade66b6a74764f4eae31d9c87Josef 'Jeff' Sipek mstream->istream.max_buffer_size = block_size;
dd4f30895ebbddd77e000472fbadcb3128ae2883Timo Sirainen mstream->istream.read = _read;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mstream->istream.seek = _seek;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mstream->istream.sync = _sync;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mstream->istream.stat = _stat;
dd4f30895ebbddd77e000472fbadcb3128ae2883Timo Sirainen
dd4f30895ebbddd77e000472fbadcb3128ae2883Timo Sirainen istream = i_stream_create(&mstream->istream, fd, start_offset);
dd4f30895ebbddd77e000472fbadcb3128ae2883Timo Sirainen istream->mmaped = TRUE;
dd4f30895ebbddd77e000472fbadcb3128ae2883Timo Sirainen istream->blocking = TRUE;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen istream->seekable = TRUE;
dd4f30895ebbddd77e000472fbadcb3128ae2883Timo Sirainen return istream;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen}
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen