bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2002-2018 Dovecot authors, see the included COPYING file */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
5254d77805cd35b9356d072ba325c356c43b0d51Timo Sirainen/* @UNSAFE: whole file */
5254d77805cd35b9356d072ba325c356c43b0d51Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen#include "lib.h"
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen#include "ioloop.h"
bf132be3fe1c9e8de84f10d0b05c0b46ca542ac4Timo Sirainen#include "istream-file-private.h"
bdd36cfdba3ff66d25570a9ff568d69e1eb543cfTimo Sirainen#include "net.h"
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen#include <time.h>
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen#include <unistd.h>
09801f106cd531a28b4e03ec665e44c421264560Timo Sirainen#include <fcntl.h>
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen#include <sys/stat.h>
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
bf132be3fe1c9e8de84f10d0b05c0b46ca542ac4Timo Sirainenvoid i_stream_file_close(struct iostream_private *stream,
bf132be3fe1c9e8de84f10d0b05c0b46ca542ac4Timo Sirainen bool close_parent ATTR_UNUSED)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen{
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen struct file_istream *fstream = (struct file_istream *)stream;
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen struct istream_private *_stream = (struct istream_private *)stream;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (fstream->autoclose_fd && _stream->fd != -1) {
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen if (close(_stream->fd) < 0) {
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen i_error("file_istream.close(%s) failed: %m",
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen i_stream_get_name(&_stream->istream));
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen }
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen }
2c25e1360d4b5cc55eda969a3a7204d950de5a8fTimo Sirainen _stream->fd = -1;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen}
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
09801f106cd531a28b4e03ec665e44c421264560Timo Sirainenstatic int i_stream_file_open(struct istream_private *stream)
09801f106cd531a28b4e03ec665e44c421264560Timo Sirainen{
09801f106cd531a28b4e03ec665e44c421264560Timo Sirainen const char *path = i_stream_get_name(&stream->istream);
09801f106cd531a28b4e03ec665e44c421264560Timo Sirainen
09801f106cd531a28b4e03ec665e44c421264560Timo Sirainen stream->fd = open(path, O_RDONLY);
09801f106cd531a28b4e03ec665e44c421264560Timo Sirainen if (stream->fd == -1) {
1c6f6f5bef70f16546b3bc8f4cd5f93f373e82a2Timo Sirainen io_stream_set_error(&stream->iostream,
1c6f6f5bef70f16546b3bc8f4cd5f93f373e82a2Timo Sirainen "open(%s) failed: %m", path);
09801f106cd531a28b4e03ec665e44c421264560Timo Sirainen stream->istream.stream_errno = errno;
09801f106cd531a28b4e03ec665e44c421264560Timo Sirainen return -1;
09801f106cd531a28b4e03ec665e44c421264560Timo Sirainen }
09801f106cd531a28b4e03ec665e44c421264560Timo Sirainen return 0;
09801f106cd531a28b4e03ec665e44c421264560Timo Sirainen}
09801f106cd531a28b4e03ec665e44c421264560Timo Sirainen
bf132be3fe1c9e8de84f10d0b05c0b46ca542ac4Timo Sirainenssize_t i_stream_file_read(struct istream_private *stream)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen{
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen struct file_istream *fstream = (struct file_istream *) stream;
5024c4799b324ea15270152b775c67ccfc72d5bcTimo Sirainen uoff_t offset;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen size_t size;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen ssize_t ret;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
dd2df6a67f10792ce31a3666197c0b6885893a3aTimo Sirainen if (!i_stream_try_alloc(stream, 1, &size))
14175321ddb88619015866978c05a27786ca4814Timo Sirainen return -2;
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen
09801f106cd531a28b4e03ec665e44c421264560Timo Sirainen if (stream->fd == -1) {
09801f106cd531a28b4e03ec665e44c421264560Timo Sirainen if (i_stream_file_open(stream) < 0)
09801f106cd531a28b4e03ec665e44c421264560Timo Sirainen return -1;
abb404575a238f27ea03b6049880f30f1656ddc4Timo Sirainen i_assert(stream->fd != -1);
09801f106cd531a28b4e03ec665e44c421264560Timo Sirainen }
09801f106cd531a28b4e03ec665e44c421264560Timo Sirainen
5024c4799b324ea15270152b775c67ccfc72d5bcTimo Sirainen offset = stream->istream.v_offset + (stream->pos - stream->skip);
03915cfec4eb1b5a65e5b6b676c8f4151bc80351Timo Sirainen
03915cfec4eb1b5a65e5b6b676c8f4151bc80351Timo Sirainen if (fstream->file) {
03915cfec4eb1b5a65e5b6b676c8f4151bc80351Timo Sirainen ret = pread(stream->fd, stream->w_buffer + stream->pos,
03915cfec4eb1b5a65e5b6b676c8f4151bc80351Timo Sirainen size, offset);
03915cfec4eb1b5a65e5b6b676c8f4151bc80351Timo Sirainen } else if (fstream->seen_eof) {
03915cfec4eb1b5a65e5b6b676c8f4151bc80351Timo Sirainen /* don't try to read() again. EOF from keyboard (^D)
03915cfec4eb1b5a65e5b6b676c8f4151bc80351Timo Sirainen requires this to work right. */
03915cfec4eb1b5a65e5b6b676c8f4151bc80351Timo Sirainen ret = 0;
03915cfec4eb1b5a65e5b6b676c8f4151bc80351Timo Sirainen } else {
03915cfec4eb1b5a65e5b6b676c8f4151bc80351Timo Sirainen ret = read(stream->fd, stream->w_buffer + stream->pos,
03915cfec4eb1b5a65e5b6b676c8f4151bc80351Timo Sirainen size);
03915cfec4eb1b5a65e5b6b676c8f4151bc80351Timo Sirainen }
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen if (ret == 0) {
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen /* EOF */
9e095dd6a77097356aca8216356d4d71ef1bea45Timo Sirainen stream->istream.eof = TRUE;
8edc373587d75f8040e3c4416e50638aa2a32188Timo Sirainen fstream->seen_eof = TRUE;
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen return -1;
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen }
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainen if (unlikely(ret < 0)) {
03915cfec4eb1b5a65e5b6b676c8f4151bc80351Timo Sirainen if ((errno == EINTR || errno == EAGAIN) &&
03915cfec4eb1b5a65e5b6b676c8f4151bc80351Timo Sirainen !stream->istream.blocking) {
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen ret = 0;
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen } else {
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen i_assert(errno != 0);
9f131c8b6d88ffc65d94eae63e0b3c11d7c24cb9Timo Sirainen /* if we get EBADF for a valid fd, it means something's
9f131c8b6d88ffc65d94eae63e0b3c11d7c24cb9Timo Sirainen really wrong and we'd better just crash. */
9f131c8b6d88ffc65d94eae63e0b3c11d7c24cb9Timo Sirainen i_assert(errno != EBADF);
5024c4799b324ea15270152b775c67ccfc72d5bcTimo Sirainen if (fstream->file) {
5024c4799b324ea15270152b775c67ccfc72d5bcTimo Sirainen io_stream_set_error(&stream->iostream,
5024c4799b324ea15270152b775c67ccfc72d5bcTimo Sirainen "pread(size=%"PRIuSIZE_T
5024c4799b324ea15270152b775c67ccfc72d5bcTimo Sirainen " offset=%"PRIuUOFF_T") failed: %m",
5024c4799b324ea15270152b775c67ccfc72d5bcTimo Sirainen size, offset);
5024c4799b324ea15270152b775c67ccfc72d5bcTimo Sirainen } else {
5024c4799b324ea15270152b775c67ccfc72d5bcTimo Sirainen io_stream_set_error(&stream->iostream,
5024c4799b324ea15270152b775c67ccfc72d5bcTimo Sirainen "read(size=%"PRIuSIZE_T") failed: %m",
5024c4799b324ea15270152b775c67ccfc72d5bcTimo Sirainen size);
5024c4799b324ea15270152b775c67ccfc72d5bcTimo Sirainen }
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);
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen i_assert(ret != -1);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen return ret;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen}
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainenstatic void i_stream_file_seek(struct istream_private *stream, uoff_t v_offset,
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen bool mark ATTR_UNUSED)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen{
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen struct file_istream *fstream = (struct file_istream *) stream;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
411d6baa37f31d90730e90c4a28c43e1974bbe58Timo Sirainen if (!stream->istream.seekable) {
4ae354df6e08998137b527f495bfaaf3daf9eddcTimo Sirainen if (v_offset < stream->istream.v_offset)
4ae354df6e08998137b527f495bfaaf3daf9eddcTimo Sirainen i_panic("stream doesn't support seeking backwards");
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen fstream->skip_left += v_offset - stream->istream.v_offset;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen }
143cb2e0744e647f8fc637bbdea1106c1587a4bfTimo Sirainen
143cb2e0744e647f8fc637bbdea1106c1587a4bfTimo Sirainen stream->istream.v_offset = v_offset;
143cb2e0744e647f8fc637bbdea1106c1587a4bfTimo Sirainen stream->skip = stream->pos = 0;
8edc373587d75f8040e3c4416e50638aa2a32188Timo Sirainen fstream->seen_eof = FALSE;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen}
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainenstatic void i_stream_file_sync(struct istream_private *stream)
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo 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;
30c795b3ee48d753b75b2db8bfd4b88792017122Timo Sirainen stream->istream.eof = FALSE;
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen}
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen
01f4ee4a0243f3fe9af763e1a540cd5cff0d63f5Timo Sirainenstatic int
a94936bafd127680184da114c6a177b37ff656e5Timo Siraineni_stream_file_stat(struct istream_private *stream, bool exact ATTR_UNUSED)
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen{
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen struct file_istream *fstream = (struct file_istream *) stream;
09801f106cd531a28b4e03ec665e44c421264560Timo Sirainen const char *name = i_stream_get_name(&stream->istream);
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen
09801f106cd531a28b4e03ec665e44c421264560Timo Sirainen if (!fstream->file) {
09801f106cd531a28b4e03ec665e44c421264560Timo Sirainen /* return defaults */
09801f106cd531a28b4e03ec665e44c421264560Timo Sirainen } else if (stream->fd != -1) {
09801f106cd531a28b4e03ec665e44c421264560Timo Sirainen if (fstat(stream->fd, &stream->statbuf) < 0) {
e17d72cec1c75554483d692edd687b411526f312Timo Sirainen stream->istream.stream_errno = errno;
e17d72cec1c75554483d692edd687b411526f312Timo Sirainen io_stream_set_error(&stream->iostream,
e17d72cec1c75554483d692edd687b411526f312Timo Sirainen "file_istream.fstat(%s) failed: %m", name);
e17d72cec1c75554483d692edd687b411526f312Timo Sirainen i_error("%s", i_stream_get_error(&stream->istream));
01f4ee4a0243f3fe9af763e1a540cd5cff0d63f5Timo Sirainen return -1;
09801f106cd531a28b4e03ec665e44c421264560Timo Sirainen }
09801f106cd531a28b4e03ec665e44c421264560Timo Sirainen } else {
09801f106cd531a28b4e03ec665e44c421264560Timo Sirainen if (stat(name, &stream->statbuf) < 0) {
e17d72cec1c75554483d692edd687b411526f312Timo Sirainen stream->istream.stream_errno = errno;
e17d72cec1c75554483d692edd687b411526f312Timo Sirainen io_stream_set_error(&stream->iostream,
e17d72cec1c75554483d692edd687b411526f312Timo Sirainen "file_istream.stat(%s) failed: %m", name);
e17d72cec1c75554483d692edd687b411526f312Timo Sirainen i_error("%s", i_stream_get_error(&stream->istream));
01f4ee4a0243f3fe9af763e1a540cd5cff0d63f5Timo Sirainen return -1;
cd1eef2109b4476842b7757f1d69b104196d5941Timo Sirainen }
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen }
01f4ee4a0243f3fe9af763e1a540cd5cff0d63f5Timo Sirainen return 0;
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen}
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen
bf132be3fe1c9e8de84f10d0b05c0b46ca542ac4Timo Sirainenstruct istream *
bf132be3fe1c9e8de84f10d0b05c0b46ca542ac4Timo Siraineni_stream_create_file_common(struct file_istream *fstream,
bf132be3fe1c9e8de84f10d0b05c0b46ca542ac4Timo Sirainen int fd, const char *path,
1c6f6f5bef70f16546b3bc8f4cd5f93f373e82a2Timo Sirainen size_t max_buffer_size, bool autoclose_fd)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen{
9a755930537f13e9746c4fc8c1bc42a83e52275eTimo Sirainen struct istream *input;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen struct stat st;
331b4805d76c0b3a5a38a560276f3cf110f55ba0Timo Sirainen bool is_file;
f363414461e991a478d015861344974714620f3bTimo Sirainen int flags;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen fstream->autoclose_fd = autoclose_fd;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen fstream->istream.iostream.close = i_stream_file_close;
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen fstream->istream.max_buffer_size = max_buffer_size;
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen fstream->istream.read = i_stream_file_read;
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen fstream->istream.seek = i_stream_file_seek;
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen fstream->istream.sync = i_stream_file_sync;
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen fstream->istream.stat = i_stream_file_stat;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen /* if it's a file, set the flags properly */
f363414461e991a478d015861344974714620f3bTimo Sirainen if (fd == -1) {
f363414461e991a478d015861344974714620f3bTimo Sirainen /* only the path is known for now - the fd is opened later */
331b4805d76c0b3a5a38a560276f3cf110f55ba0Timo Sirainen is_file = TRUE;
f363414461e991a478d015861344974714620f3bTimo Sirainen } else if (fstat(fd, &st) < 0)
331b4805d76c0b3a5a38a560276f3cf110f55ba0Timo Sirainen is_file = FALSE;
331b4805d76c0b3a5a38a560276f3cf110f55ba0Timo Sirainen else if (S_ISREG(st.st_mode))
331b4805d76c0b3a5a38a560276f3cf110f55ba0Timo Sirainen is_file = TRUE;
331b4805d76c0b3a5a38a560276f3cf110f55ba0Timo Sirainen else if (!S_ISDIR(st.st_mode))
331b4805d76c0b3a5a38a560276f3cf110f55ba0Timo Sirainen is_file = FALSE;
331b4805d76c0b3a5a38a560276f3cf110f55ba0Timo Sirainen else {
331b4805d76c0b3a5a38a560276f3cf110f55ba0Timo Sirainen /* we're trying to open a directory.
331b4805d76c0b3a5a38a560276f3cf110f55ba0Timo Sirainen we're not designed for it. */
1c6f6f5bef70f16546b3bc8f4cd5f93f373e82a2Timo Sirainen io_stream_set_error(&fstream->istream.iostream,
1c6f6f5bef70f16546b3bc8f4cd5f93f373e82a2Timo Sirainen "%s is a directory, can't read it as file",
1c6f6f5bef70f16546b3bc8f4cd5f93f373e82a2Timo Sirainen path != NULL ? path : t_strdup_printf("<fd %d>", fd));
331b4805d76c0b3a5a38a560276f3cf110f55ba0Timo Sirainen fstream->istream.istream.stream_errno = EISDIR;
331b4805d76c0b3a5a38a560276f3cf110f55ba0Timo Sirainen is_file = FALSE;
331b4805d76c0b3a5a38a560276f3cf110f55ba0Timo Sirainen }
331b4805d76c0b3a5a38a560276f3cf110f55ba0Timo Sirainen if (is_file) {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen fstream->file = TRUE;
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen fstream->istream.istream.blocking = TRUE;
411d6baa37f31d90730e90c4a28c43e1974bbe58Timo Sirainen fstream->istream.istream.seekable = TRUE;
f363414461e991a478d015861344974714620f3bTimo Sirainen } else if ((flags = fcntl(fd, F_GETFL, 0)) < 0) {
f363414461e991a478d015861344974714620f3bTimo Sirainen /* shouldn't happen */
f363414461e991a478d015861344974714620f3bTimo Sirainen fstream->istream.istream.stream_errno = errno;
f363414461e991a478d015861344974714620f3bTimo Sirainen io_stream_set_error(&fstream->istream.iostream,
f363414461e991a478d015861344974714620f3bTimo Sirainen "fcntl(%d, F_GETFL) failed: %m", fd);
f363414461e991a478d015861344974714620f3bTimo Sirainen } else if ((flags & O_NONBLOCK) == 0) {
f363414461e991a478d015861344974714620f3bTimo Sirainen /* blocking socket/fifo */
f363414461e991a478d015861344974714620f3bTimo Sirainen fstream->istream.istream.blocking = TRUE;
411d6baa37f31d90730e90c4a28c43e1974bbe58Timo Sirainen }
da2aa032ccfa8e7e4a4380ef738014549f4d2c2dTimo Sirainen fstream->istream.istream.readable_fd = TRUE;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
2974dca6be5120e49279f06c8aa952e5fac56048Timo Sirainen input = i_stream_create(&fstream->istream, NULL, fd, 0);
9a755930537f13e9746c4fc8c1bc42a83e52275eTimo Sirainen i_stream_set_name(input, is_file ? "(file)" : "(fd)");
9a755930537f13e9746c4fc8c1bc42a83e52275eTimo Sirainen return input;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen}
09801f106cd531a28b4e03ec665e44c421264560Timo Sirainen
e93184a9055c2530366dfe617e07199603c399ddMartti Rannanjärvistruct istream *i_stream_create_fd(int fd, size_t max_buffer_size)
09801f106cd531a28b4e03ec665e44c421264560Timo Sirainen{
bf132be3fe1c9e8de84f10d0b05c0b46ca542ac4Timo Sirainen struct file_istream *fstream;
bf132be3fe1c9e8de84f10d0b05c0b46ca542ac4Timo Sirainen
09801f106cd531a28b4e03ec665e44c421264560Timo Sirainen i_assert(fd != -1);
09801f106cd531a28b4e03ec665e44c421264560Timo Sirainen
bf132be3fe1c9e8de84f10d0b05c0b46ca542ac4Timo Sirainen fstream = i_new(struct file_istream, 1);
bf132be3fe1c9e8de84f10d0b05c0b46ca542ac4Timo Sirainen return i_stream_create_file_common(fstream, fd, NULL,
e93184a9055c2530366dfe617e07199603c399ddMartti Rannanjärvi max_buffer_size, FALSE);
09801f106cd531a28b4e03ec665e44c421264560Timo Sirainen}
09801f106cd531a28b4e03ec665e44c421264560Timo Sirainen
43834f87bf431198f986e86052a4f6e558fdb07dTimo Sirainenstruct istream *i_stream_create_fd_autoclose(int *fd, size_t max_buffer_size)
43834f87bf431198f986e86052a4f6e558fdb07dTimo Sirainen{
43834f87bf431198f986e86052a4f6e558fdb07dTimo Sirainen struct istream *input;
e93184a9055c2530366dfe617e07199603c399ddMartti Rannanjärvi struct file_istream *fstream;
e93184a9055c2530366dfe617e07199603c399ddMartti Rannanjärvi
e93184a9055c2530366dfe617e07199603c399ddMartti Rannanjärvi i_assert(*fd != -1);
43834f87bf431198f986e86052a4f6e558fdb07dTimo Sirainen
e93184a9055c2530366dfe617e07199603c399ddMartti Rannanjärvi fstream = i_new(struct file_istream, 1);
e93184a9055c2530366dfe617e07199603c399ddMartti Rannanjärvi input = i_stream_create_file_common(fstream, *fd, NULL,
e93184a9055c2530366dfe617e07199603c399ddMartti Rannanjärvi max_buffer_size, TRUE);
43834f87bf431198f986e86052a4f6e558fdb07dTimo Sirainen *fd = -1;
43834f87bf431198f986e86052a4f6e558fdb07dTimo Sirainen return input;
43834f87bf431198f986e86052a4f6e558fdb07dTimo Sirainen}
43834f87bf431198f986e86052a4f6e558fdb07dTimo Sirainen
09801f106cd531a28b4e03ec665e44c421264560Timo Sirainenstruct istream *i_stream_create_file(const char *path, size_t max_buffer_size)
09801f106cd531a28b4e03ec665e44c421264560Timo Sirainen{
bf132be3fe1c9e8de84f10d0b05c0b46ca542ac4Timo Sirainen struct file_istream *fstream;
09801f106cd531a28b4e03ec665e44c421264560Timo Sirainen struct istream *input;
09801f106cd531a28b4e03ec665e44c421264560Timo Sirainen
bf132be3fe1c9e8de84f10d0b05c0b46ca542ac4Timo Sirainen fstream = i_new(struct file_istream, 1);
bf132be3fe1c9e8de84f10d0b05c0b46ca542ac4Timo Sirainen input = i_stream_create_file_common(fstream, -1, path,
bf132be3fe1c9e8de84f10d0b05c0b46ca542ac4Timo Sirainen max_buffer_size, TRUE);
09801f106cd531a28b4e03ec665e44c421264560Timo Sirainen i_stream_set_name(input, path);
09801f106cd531a28b4e03ec665e44c421264560Timo Sirainen return input;
09801f106cd531a28b4e03ec665e44c421264560Timo Sirainen}