istream-mmap.c revision 0536ccb51d41e3078c3a9fa33e509fb4b2420f95
45312f52ff3a3d4c137447be4c7556500c2f8bf2Timo Sirainen/* Copyright (c) 2002-2011 Dovecot authors, see the included COPYING file */
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "lib.h"
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen#include "ioloop.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "mmap-util.h"
ea5f188fc29dfaa0c4071e6413e16e1d04263722Timo Sirainen#include "istream-private.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include <unistd.h>
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include <sys/stat.h>
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen
63a61b7a739ae0f3f520215137d9c50f94d0f34fTimo Sirainenstruct mmap_istream {
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen struct istream_private istream;
18565c69efcd7db003dbf27cf625ed822e889fb1Timo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen struct timeval fstat_cache_stamp;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen void *mmap_base;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen off_t mmap_offset;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen uoff_t v_size;
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen unsigned int autoclose_fd:1;
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen};
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainenstatic size_t mmap_pagemask = 0;
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainenstatic void i_stream_mmap_close(struct iostream_private *stream)
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen{
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen struct mmap_istream *mstream = (struct mmap_istream *) stream;
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen if (mstream->autoclose_fd && mstream->istream.fd != -1) {
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen if (close(mstream->istream.fd) < 0) {
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen i_error("mmap_istream.close(%s) failed: %m",
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen i_stream_get_name(&mstream->istream.istream));
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen }
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen }
af1f4b17a92ca7b2661737e65c7849df289d3070Timo Sirainen mstream->istream.fd = -1;
af1f4b17a92ca7b2661737e65c7849df289d3070Timo Sirainen}
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainenstatic void i_stream_munmap(struct mmap_istream *mstream)
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen{
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen struct istream_private *_stream = &mstream->istream;
01cbf4ac5d44137ab434791be7f838d98d0fcf3bTimo Sirainen
4b41116563110d00330896a568eff1078c382827Timo Sirainen if (_stream->buffer != NULL) {
4b41116563110d00330896a568eff1078c382827Timo Sirainen if (munmap(mstream->mmap_base, _stream->buffer_size) < 0) {
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen i_error("mmap_istream.munmap(%s) failed: %m",
ebe6df72f1309135f02b6a4d2aef1e81a073f91cTimo Sirainen i_stream_get_name(&_stream->istream));
ebe6df72f1309135f02b6a4d2aef1e81a073f91cTimo Sirainen }
ebe6df72f1309135f02b6a4d2aef1e81a073f91cTimo Sirainen mstream->mmap_base = NULL;
b12a6d0e54318273acf0d0fb8b3f4c29f67b62b0Timo Sirainen _stream->buffer = NULL;
b12a6d0e54318273acf0d0fb8b3f4c29f67b62b0Timo Sirainen _stream->buffer_size = 0;
b12a6d0e54318273acf0d0fb8b3f4c29f67b62b0Timo Sirainen mstream->mmap_offset = 0;
b12a6d0e54318273acf0d0fb8b3f4c29f67b62b0Timo Sirainen }
b12a6d0e54318273acf0d0fb8b3f4c29f67b62b0Timo Sirainen}
b12a6d0e54318273acf0d0fb8b3f4c29f67b62b0Timo Sirainen
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainenstatic void i_stream_mmap_destroy(struct iostream_private *stream)
73247459cf41eb1e5ae5bc61354db46d3b05ee75Timo Sirainen{
73247459cf41eb1e5ae5bc61354db46d3b05ee75Timo Sirainen struct mmap_istream *mstream = (struct mmap_istream *) stream;
73247459cf41eb1e5ae5bc61354db46d3b05ee75Timo Sirainen
73247459cf41eb1e5ae5bc61354db46d3b05ee75Timo Sirainen i_stream_munmap(mstream);
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen}
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainenstatic size_t mstream_get_mmap_block_size(struct istream_private *stream)
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen{
73247459cf41eb1e5ae5bc61354db46d3b05ee75Timo Sirainen return (stream->max_buffer_size + mmap_get_page_size() - 1) & ~
73247459cf41eb1e5ae5bc61354db46d3b05ee75Timo Sirainen (mmap_get_page_size() - 1);
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen}
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainenstatic ssize_t i_stream_mmap_read(struct istream_private *stream)
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen{
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen struct mmap_istream *mstream = (struct mmap_istream *) stream;
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen size_t aligned_skip;
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen uoff_t top;
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen if (stream->pos < stream->buffer_size) {
73247459cf41eb1e5ae5bc61354db46d3b05ee75Timo Sirainen /* more bytes available without needing to mmap() */
73247459cf41eb1e5ae5bc61354db46d3b05ee75Timo Sirainen stream->pos = stream->buffer_size;
73247459cf41eb1e5ae5bc61354db46d3b05ee75Timo Sirainen return stream->pos - stream->skip;
73247459cf41eb1e5ae5bc61354db46d3b05ee75Timo Sirainen }
73247459cf41eb1e5ae5bc61354db46d3b05ee75Timo Sirainen
73247459cf41eb1e5ae5bc61354db46d3b05ee75Timo Sirainen if (stream->istream.v_offset >= mstream->v_size) {
73247459cf41eb1e5ae5bc61354db46d3b05ee75Timo Sirainen stream->istream.eof = TRUE;
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen return -1;
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen }
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen
597dce34068d603fb759b4dff404b34049213e51Timo Sirainen aligned_skip = stream->skip & ~mmap_pagemask;
63a61b7a739ae0f3f520215137d9c50f94d0f34fTimo Sirainen if (aligned_skip == 0 && mstream->mmap_base != NULL) {
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen /* didn't skip enough bytes */
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen return -2;
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen }
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen stream->skip -= aligned_skip;
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen mstream->mmap_offset += aligned_skip;
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen
4b41116563110d00330896a568eff1078c382827Timo Sirainen if (mstream->mmap_base != NULL) {
910fa4e4204a73d3d24c03f3059dd24e727ca057Timo Sirainen if (munmap(mstream->mmap_base, stream->buffer_size) < 0) {
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen i_error("mmap_istream.munmap(%s) failed: %m",
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen i_stream_get_name(&stream->istream));
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen }
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen }
6060b7c8edf8fce73470d0df6a2479b69b01c537Timo Sirainen
7f773564b94e6054a40d3785cb63c29f1e4d4deeTimo Sirainen top = mstream->v_size - mstream->mmap_offset;
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen stream->buffer_size = I_MIN(top, mstream_get_mmap_block_size(stream));
ccc895c0358108d2304239063e940b7d75f364abTimo Sirainen
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen i_assert((uoff_t)mstream->mmap_offset + stream->buffer_size <=
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen mstream->v_size);
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen
4b41116563110d00330896a568eff1078c382827Timo Sirainen if (stream->buffer_size == 0) {
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen /* don't bother even trying mmap */
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen mstream->mmap_base = NULL;
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen stream->buffer = NULL;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen } else {
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen mstream->mmap_base =
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen mmap(NULL, stream->buffer_size, PROT_READ, MAP_PRIVATE,
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen stream->fd, mstream->mmap_offset);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen if (mstream->mmap_base == MAP_FAILED) {
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen i_assert(errno != 0);
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen stream->istream.stream_errno = errno;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen mstream->mmap_base = NULL;
4b41116563110d00330896a568eff1078c382827Timo Sirainen stream->buffer = NULL;
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen stream->buffer_size = 0;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen stream->skip = stream->pos = 0;
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen i_error("mmap_istream.mmap(%s) failed: %m",
345212e8f61ebf14ff4f80df26df9e655eb5121eTimo Sirainen i_stream_get_name(&stream->istream));
345212e8f61ebf14ff4f80df26df9e655eb5121eTimo Sirainen return -1;
345212e8f61ebf14ff4f80df26df9e655eb5121eTimo Sirainen }
345212e8f61ebf14ff4f80df26df9e655eb5121eTimo Sirainen stream->buffer = mstream->mmap_base;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen }
345212e8f61ebf14ff4f80df26df9e655eb5121eTimo Sirainen
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen if (stream->buffer_size > mmap_get_page_size()) {
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen if (madvise(mstream->mmap_base, stream->buffer_size,
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen MADV_SEQUENTIAL) < 0) {
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen i_error("mmap_istream.madvise(%s): %m",
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen i_stream_get_name(&stream->istream));
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen }
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen }
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen stream->pos = stream->buffer_size;
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen i_assert(stream->pos - stream->skip > 0);
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen return stream->pos - stream->skip;
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen}
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainenstatic void i_stream_mmap_seek(struct istream_private *stream, uoff_t v_offset,
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen bool mark ATTR_UNUSED)
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen{
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen struct mmap_istream *mstream = (struct mmap_istream *) stream;
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen if (stream->buffer_size != 0 &&
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen (uoff_t)mstream->mmap_offset <= v_offset &&
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainen (uoff_t)mstream->mmap_offset + stream->buffer_size > v_offset) {
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainen /* already mmaped */
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainen stream->skip = stream->pos = v_offset - mstream->mmap_offset;
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainen } else {
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainen /* force reading next time */
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainen i_stream_munmap(mstream);
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainen stream->skip = stream->pos = v_offset;
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainen }
bf9402875418faf11825cf11fbe06326b6086e3dTimo Sirainen
bf9402875418faf11825cf11fbe06326b6086e3dTimo Sirainen stream->istream.v_offset = v_offset;
bf9402875418faf11825cf11fbe06326b6086e3dTimo Sirainen}
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainen
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainenstatic void i_stream_mmap_sync(struct istream_private *stream)
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainen{
bf9402875418faf11825cf11fbe06326b6086e3dTimo Sirainen struct mmap_istream *mstream = (struct mmap_istream *) stream;
bf9402875418faf11825cf11fbe06326b6086e3dTimo Sirainen
bf9402875418faf11825cf11fbe06326b6086e3dTimo Sirainen i_stream_munmap(mstream);
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainen stream->skip = stream->pos = stream->istream.v_offset;
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainen
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainen mstream->fstat_cache_stamp.tv_sec = 0;
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainen}
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainen
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainenstatic int fstat_cached(struct mmap_istream *mstream)
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen{
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen if (mstream->fstat_cache_stamp.tv_sec == ioloop_timeval.tv_sec &&
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen mstream->fstat_cache_stamp.tv_usec == ioloop_timeval.tv_usec)
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen return 0;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen if (fstat(mstream->istream.fd, &mstream->istream.statbuf) < 0) {
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen i_error("mmap_istream.fstat(%s) failed: %m",
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen i_stream_get_name(&mstream->istream.istream));
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen return -1;
4b41116563110d00330896a568eff1078c382827Timo Sirainen }
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen mstream->fstat_cache_stamp = ioloop_timeval;
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen return 0;
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen}
ee3e01f75b1db691bf20dd4e2558965421b8f937Timo Sirainen
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainenstatic const struct stat *
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Siraineni_stream_mmap_stat(struct istream_private *stream, bool exact ATTR_UNUSED)
ea5f188fc29dfaa0c4071e6413e16e1d04263722Timo Sirainen{
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen struct mmap_istream *mstream = (struct mmap_istream *) stream;
ea5f188fc29dfaa0c4071e6413e16e1d04263722Timo Sirainen
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen if (fstat_cached(mstream) < 0)
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen return NULL;
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen return &stream->statbuf;
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen}
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainenstruct istream *i_stream_create_mmap(int fd, size_t block_size,
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainen uoff_t start_offset, uoff_t v_size,
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainen bool autoclose_fd)
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainen{
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainen struct mmap_istream *mstream;
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainen struct istream *istream;
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen struct stat st;
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen if (mmap_pagemask == 0)
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen mmap_pagemask = mmap_get_page_size()-1;
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen if (v_size == 0) {
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen if (fstat(fd, &st) < 0)
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen i_error("i_stream_create_mmap(): fstat() failed: %m");
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen else {
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen v_size = st.st_size;
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen if (start_offset > v_size)
54d42552005111841ab45ec9ca7559075fabd5dfTimo Sirainen start_offset = v_size;
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen v_size -= start_offset;
54d42552005111841ab45ec9ca7559075fabd5dfTimo Sirainen }
54d42552005111841ab45ec9ca7559075fabd5dfTimo Sirainen }
5abb33fdc94c081ccd3213bf7d0fa9d0367b4bfdTimo Sirainen
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen mstream = i_new(struct mmap_istream, 1);
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen mstream->autoclose_fd = autoclose_fd;
54d42552005111841ab45ec9ca7559075fabd5dfTimo Sirainen mstream->v_size = v_size;
54d42552005111841ab45ec9ca7559075fabd5dfTimo Sirainen
5abb33fdc94c081ccd3213bf7d0fa9d0367b4bfdTimo Sirainen mstream->istream.iostream.close = i_stream_mmap_close;
54d42552005111841ab45ec9ca7559075fabd5dfTimo Sirainen mstream->istream.iostream.destroy = i_stream_mmap_destroy;
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen
54d42552005111841ab45ec9ca7559075fabd5dfTimo Sirainen mstream->istream.max_buffer_size = block_size;
8ed8c821ba8aab0b4ed0375f87d48737ef0e0d8eTimo Sirainen mstream->istream.read = i_stream_mmap_read;
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen mstream->istream.seek = i_stream_mmap_seek;
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen mstream->istream.sync = i_stream_mmap_sync;
8ed8c821ba8aab0b4ed0375f87d48737ef0e0d8eTimo Sirainen mstream->istream.stat = i_stream_mmap_stat;
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen mstream->istream.istream.readable_fd = TRUE;
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen mstream->istream.abs_start_offset = start_offset;
54d42552005111841ab45ec9ca7559075fabd5dfTimo Sirainen istream = i_stream_create(&mstream->istream, NULL, fd);
54d42552005111841ab45ec9ca7559075fabd5dfTimo Sirainen istream->mmaped = TRUE;
54d42552005111841ab45ec9ca7559075fabd5dfTimo Sirainen istream->blocking = TRUE;
54d42552005111841ab45ec9ca7559075fabd5dfTimo Sirainen istream->seekable = TRUE;
54d42552005111841ab45ec9ca7559075fabd5dfTimo Sirainen return istream;
54d42552005111841ab45ec9ca7559075fabd5dfTimo Sirainen}
54d42552005111841ab45ec9ca7559075fabd5dfTimo Sirainen