istream-mmap.c revision 03f5c621d06d6b6d77a145196c9633a7aa64dc78
02c335c23bf5fa225a467c19f2c063fb0dc7b8c3Timo Sirainen/*
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch istream-mmap.c : Input stream handling for mmap()ed files
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch Copyright (c) 2002 Timo Sirainen
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch Permission is hereby granted, free of charge, to any person obtaining
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch a copy of this software and associated documentation files (the
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch "Software"), to deal in the Software without restriction, including
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch without limitation the rights to use, copy, modify, merge, publish,
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch distribute, sublicense, and/or sell copies of the Software, and to
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch permit persons to whom the Software is furnished to do so, subject to
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch the following conditions:
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch The above copyright notice and this permission notice shall be
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch included in all copies or substantial portions of the Software.
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch*/
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch#include "lib.h"
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch#include "mmap-util.h"
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch#include "istream-internal.h"
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch#include <unistd.h>
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch#include <sys/stat.h>
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Boschstruct mmap_istream {
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch struct _istream istream;
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch int fd;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch void *mmap_base;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch off_t mmap_offset;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch size_t mmap_block_size;
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch unsigned int autoclose_fd:1;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch};
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
45324f1eafa565dbc65e4dd335de9507dead55e6Timo Sirainenstatic size_t mmap_pagesize = 0;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Boschstatic size_t mmap_pagemask = 0;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Boschstatic void _close(struct _iostream *stream)
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch{
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch struct mmap_istream *mstream = (struct mmap_istream *) stream;
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch if (mstream->autoclose_fd && mstream->fd != -1) {
833bed942977673526c72e79bccc09314fc57104Phil Carmody if (close(mstream->fd) < 0)
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch i_error("mmap_istream.close() failed: %m");
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch mstream->fd = -1;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch }
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch}
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
e9228a3918aa0243eff4aae1ff5462bd3198417fTimo Sirainenstatic void i_stream_munmap(struct mmap_istream *mstream)
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch{
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch struct _istream *_stream = &mstream->istream;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
1e9296de32c9ddda40f33c06556cd568ddadf71fTimo Sirainen if (_stream->buffer != NULL) {
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch if (munmap(mstream->mmap_base, _stream->buffer_size) < 0)
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch i_error("mmap_istream.munmap() failed: %m");
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch mstream->mmap_base = NULL;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch _stream->buffer = NULL;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch _stream->buffer_size = 0;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch mstream->mmap_offset = 0;
1e9296de32c9ddda40f33c06556cd568ddadf71fTimo Sirainen }
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch}
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Boschstatic void _destroy(struct _iostream *stream)
833bed942977673526c72e79bccc09314fc57104Phil Carmody{
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch struct mmap_istream *mstream = (struct mmap_istream *) stream;
833bed942977673526c72e79bccc09314fc57104Phil Carmody
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch i_stream_munmap(mstream);
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch}
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Boschstatic void _set_max_buffer_size(struct _iostream *stream, size_t max_size)
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch{
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch struct mmap_istream *mstream = (struct mmap_istream *) stream;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch /* allow only full page sizes */
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch if (max_size < mmap_pagesize)
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch mstream->mmap_block_size = mmap_pagesize;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch else {
1e9296de32c9ddda40f33c06556cd568ddadf71fTimo Sirainen if (max_size % mmap_pagesize != 0)
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch max_size += mmap_pagesize - (max_size % mmap_pagesize);
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch mstream->mmap_block_size = max_size;
faa8995f1d300e7a8917407a52bbd1b98e10bf25Timo Sirainen }
faa8995f1d300e7a8917407a52bbd1b98e10bf25Timo Sirainen}
faa8995f1d300e7a8917407a52bbd1b98e10bf25Timo Sirainen
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Boschstatic void _set_blocking(struct _iostream *stream __attr_unused__,
faa8995f1d300e7a8917407a52bbd1b98e10bf25Timo Sirainen int timeout_msecs __attr_unused__,
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch void (*timeout_cb)(void *) __attr_unused__,
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch void *context __attr_unused__)
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch{
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch /* we never block */
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch}
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Boschstatic ssize_t io_stream_set_mmaped_pos(struct _istream *stream)
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch{
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch struct mmap_istream *mstream = (struct mmap_istream *) stream;
14bd2410de3a0261d9c53c6120915027262216bdTimo Sirainen uoff_t top;
14bd2410de3a0261d9c53c6120915027262216bdTimo Sirainen
14bd2410de3a0261d9c53c6120915027262216bdTimo Sirainen i_assert((uoff_t)mstream->mmap_offset <=
9f8cef4cbc49797053c343209ea13022fdbc5a63Stephan Bosch stream->istream.start_offset + stream->istream.v_limit);
9f8cef4cbc49797053c343209ea13022fdbc5a63Stephan Bosch
faa8995f1d300e7a8917407a52bbd1b98e10bf25Timo Sirainen top = stream->istream.start_offset + stream->istream.v_limit -
9f8cef4cbc49797053c343209ea13022fdbc5a63Stephan Bosch mstream->mmap_offset;
faa8995f1d300e7a8917407a52bbd1b98e10bf25Timo Sirainen stream->pos = I_MIN(top, stream->buffer_size);
faa8995f1d300e7a8917407a52bbd1b98e10bf25Timo Sirainen
faa8995f1d300e7a8917407a52bbd1b98e10bf25Timo Sirainen return stream->pos - stream->skip;
faa8995f1d300e7a8917407a52bbd1b98e10bf25Timo Sirainen}
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Boschstatic ssize_t _read(struct _istream *stream)
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch{
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch struct mmap_istream *mstream = (struct mmap_istream *) stream;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch size_t aligned_skip, limit_size;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch uoff_t top;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch if (stream->istream.start_offset + stream->istream.v_limit <=
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch (uoff_t)mstream->mmap_offset + stream->pos) {
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch /* end of file */
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch stream->istream.stream_errno = 0;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch return -1;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch }
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch if (stream->pos < stream->buffer_size) {
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch /* more bytes available without needing to mmap() */
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch return io_stream_set_mmaped_pos(stream);
833bed942977673526c72e79bccc09314fc57104Phil Carmody }
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch aligned_skip = stream->skip & ~mmap_pagemask;
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch if (aligned_skip == 0 && mstream->mmap_base != NULL) {
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch /* didn't skip enough bytes */
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch return -2;
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch }
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch stream->skip -= aligned_skip;
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch mstream->mmap_offset += aligned_skip;
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch if (mstream->mmap_base != NULL) {
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch if (munmap(mstream->mmap_base, stream->buffer_size) < 0)
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch i_error("io_stream_read_mmaped(): munmap() failed: %m");
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch }
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch top = stream->istream.start_offset + stream->istream.v_size -
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch mstream->mmap_offset;
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch stream->buffer_size = I_MIN(top, mstream->mmap_block_size);
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch i_assert((uoff_t)mstream->mmap_offset + stream->buffer_size <=
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch stream->istream.start_offset + stream->istream.v_size);
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch mstream->mmap_base = mmap(NULL, stream->buffer_size,
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch PROT_READ, MAP_PRIVATE,
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch mstream->fd, mstream->mmap_offset);
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch if (mstream->mmap_base == MAP_FAILED) {
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch stream->istream.stream_errno = errno;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch mstream->mmap_base = NULL;
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch stream->buffer = NULL;
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch stream->buffer_size = 0;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch stream->skip = stream->pos = 0;
91a482473f200152d6713181c0e36f7a4f03ef6dTimo Sirainen i_error("mmap_istream.mmap() failed: %m");
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch return -1;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch }
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch stream->buffer = mstream->mmap_base;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch /* madvise() only if non-limited mmap()ed buffer area larger than
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch page size */
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch limit_size = stream->istream.start_offset + stream->istream.v_limit -
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch mstream->mmap_offset;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch if (limit_size > mmap_pagesize) {
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch if (limit_size > stream->buffer_size)
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch limit_size = stream->buffer_size;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch if (madvise(mstream->mmap_base, limit_size,
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch MADV_SEQUENTIAL) < 0)
85f3bd5926fff0e70b6d259a5c8074bd8cdeb9adTimo Sirainen i_error("mmap_istream.madvise(): %m");
85f3bd5926fff0e70b6d259a5c8074bd8cdeb9adTimo Sirainen }
85f3bd5926fff0e70b6d259a5c8074bd8cdeb9adTimo Sirainen
85f3bd5926fff0e70b6d259a5c8074bd8cdeb9adTimo Sirainen return io_stream_set_mmaped_pos(stream);
85f3bd5926fff0e70b6d259a5c8074bd8cdeb9adTimo Sirainen}
85f3bd5926fff0e70b6d259a5c8074bd8cdeb9adTimo Sirainen
564e117d86ce5b659f9b9570edddc566f9ebb5dfStephan Boschstatic void _seek(struct _istream *stream, uoff_t v_offset)
564e117d86ce5b659f9b9570edddc566f9ebb5dfStephan Bosch{
564e117d86ce5b659f9b9570edddc566f9ebb5dfStephan Bosch struct mmap_istream *mstream = (struct mmap_istream *) stream;
564e117d86ce5b659f9b9570edddc566f9ebb5dfStephan Bosch uoff_t abs_offset;
564e117d86ce5b659f9b9570edddc566f9ebb5dfStephan Bosch
564e117d86ce5b659f9b9570edddc566f9ebb5dfStephan Bosch abs_offset = stream->istream.start_offset + v_offset;
564e117d86ce5b659f9b9570edddc566f9ebb5dfStephan Bosch if (stream->buffer_size != 0 &&
564e117d86ce5b659f9b9570edddc566f9ebb5dfStephan Bosch (uoff_t)mstream->mmap_offset <= abs_offset &&
564e117d86ce5b659f9b9570edddc566f9ebb5dfStephan Bosch (uoff_t)mstream->mmap_offset + stream->buffer_size > abs_offset) {
564e117d86ce5b659f9b9570edddc566f9ebb5dfStephan Bosch /* already mmaped */
564e117d86ce5b659f9b9570edddc566f9ebb5dfStephan Bosch stream->skip = stream->pos = abs_offset - mstream->mmap_offset;
564e117d86ce5b659f9b9570edddc566f9ebb5dfStephan Bosch } else {
564e117d86ce5b659f9b9570edddc566f9ebb5dfStephan Bosch /* force reading next time */
564e117d86ce5b659f9b9570edddc566f9ebb5dfStephan Bosch i_stream_munmap(mstream);
564e117d86ce5b659f9b9570edddc566f9ebb5dfStephan Bosch stream->skip = stream->pos = abs_offset;
564e117d86ce5b659f9b9570edddc566f9ebb5dfStephan Bosch }
93ed69606237a08623f8294c060fa148880058f8Timo Sirainen
93ed69606237a08623f8294c060fa148880058f8Timo Sirainen stream->istream.v_offset = v_offset;
93ed69606237a08623f8294c060fa148880058f8Timo Sirainen}
93ed69606237a08623f8294c060fa148880058f8Timo Sirainen
93ed69606237a08623f8294c060fa148880058f8Timo Sirainenstatic void _skip(struct _istream *stream, uoff_t count)
93ed69606237a08623f8294c060fa148880058f8Timo Sirainen{
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch _seek(stream, stream->istream.v_offset + count);
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch}
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Boschstruct istream *i_stream_create_mmap(int fd, pool_t pool, size_t block_size,
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch uoff_t start_offset, uoff_t v_size,
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch int autoclose_fd)
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch{
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch struct mmap_istream *mstream;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch struct istream *istream;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch struct stat st;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
711e8e4c5c5d702dfa062f42a1ede5de14c151c9Stephan Bosch if (mmap_pagesize == 0) {
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch mmap_pagesize = getpagesize();
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch mmap_pagemask = mmap_pagesize-1;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch }
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch if (v_size == 0) {
711e8e4c5c5d702dfa062f42a1ede5de14c151c9Stephan Bosch if (fstat(fd, &st) < 0) {
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch i_error("i_stream_create_mmap(): fstat() failed: %m");
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch v_size = 0;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch } else {
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch v_size = st.st_size;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch if (start_offset > v_size)
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch start_offset = v_size;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch v_size -= start_offset;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch }
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch }
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch mstream = p_new(pool, struct mmap_istream, 1);
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch mstream->fd = fd;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch _set_max_buffer_size(&mstream->istream.iostream, block_size);
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch mstream->autoclose_fd = autoclose_fd;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch mstream->istream.iostream.close = _close;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch mstream->istream.iostream.destroy = _destroy;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch mstream->istream.iostream.set_max_buffer_size = _set_max_buffer_size;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch mstream->istream.iostream.set_blocking = _set_blocking;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch mstream->istream.read = _read;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch mstream->istream.skip_count = _skip;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch mstream->istream.seek = _seek;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch istream = _i_stream_create(&mstream->istream, pool, fd,
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch start_offset, v_size);
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch istream->mmaped = TRUE;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch return istream;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch}
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch