istream-unix.c revision 03915cfec4eb1b5a65e5b6b676c8f4151bc80351
2454dfa32c93c20a8522c6ed42fe057baaac9f9aStephan Bosch/* Copyright (c) 2014-2017 Dovecot authors, see the included COPYING file */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen#include "lib.h"
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen#include "fdpass.h"
d74c9f4bf7ee37f3f58a895032ea013d07294865Timo Sirainen#include "istream-file-private.h"
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen#include "istream-unix.h"
0536ccb51d41e3078c3a9fa33e509fb4b2420f95Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenstruct unix_istream {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen struct file_istream fstream;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen bool next_read_fd;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen int read_fd;
d74c9f4bf7ee37f3f58a895032ea013d07294865Timo Sirainen};
d74c9f4bf7ee37f3f58a895032ea013d07294865Timo Sirainen
d74c9f4bf7ee37f3f58a895032ea013d07294865Timo Sirainenstatic void
d74c9f4bf7ee37f3f58a895032ea013d07294865Timo Siraineni_stream_unix_close(struct iostream_private *stream, bool close_parent)
d74c9f4bf7ee37f3f58a895032ea013d07294865Timo Sirainen{
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen struct unix_istream *ustream = (struct unix_istream *)stream;
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen i_close_fd(&ustream->read_fd);
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen i_stream_file_close(stream, close_parent);
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen}
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainenstatic ssize_t i_stream_unix_read(struct istream_private *stream)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen{
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen struct unix_istream *ustream = (struct unix_istream *)stream;
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen size_t size;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen ssize_t ret;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (!ustream->next_read_fd)
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen return i_stream_file_read(stream);
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen i_assert(ustream->read_fd == -1);
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen i_assert(ustream->fstream.skip_left == 0); /* not supported here.. */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (!i_stream_try_alloc(stream, 1, &size))
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen return -2;
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen ret = fd_read(stream->fd, stream->w_buffer + stream->pos, size,
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen &ustream->read_fd);
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen if (ustream->read_fd != -1)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen ustream->next_read_fd = FALSE;
2c25e1360d4b5cc55eda969a3a7204d950de5a8fTimo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (ret == 0) {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen /* EOF */
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen stream->istream.eof = TRUE;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen ustream->fstream.seen_eof = TRUE;
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen return -1;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen }
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
d74c9f4bf7ee37f3f58a895032ea013d07294865Timo Sirainen if (unlikely(ret < 0)) {
d74c9f4bf7ee37f3f58a895032ea013d07294865Timo Sirainen if ((errno == EINTR || errno == EAGAIN) &&
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen !stream->istream.blocking) {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen return 0;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen } else {
d74c9f4bf7ee37f3f58a895032ea013d07294865Timo Sirainen i_assert(errno != 0);
d74c9f4bf7ee37f3f58a895032ea013d07294865Timo Sirainen /* if we get EBADF for a valid fd, it means something's
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen really wrong and we'd better just crash. */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen i_assert(errno != EBADF);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen stream->istream.stream_errno = errno;
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen return -1;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen }
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen }
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen stream->pos += ret;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen return ret;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen}
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainenstruct istream *i_stream_create_unix(int fd, size_t max_buffer_size)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen{
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen struct unix_istream *ustream;
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen struct istream *input;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen i_assert(fd != -1);
d74c9f4bf7ee37f3f58a895032ea013d07294865Timo Sirainen
d74c9f4bf7ee37f3f58a895032ea013d07294865Timo Sirainen ustream = i_new(struct unix_istream, 1);
d74c9f4bf7ee37f3f58a895032ea013d07294865Timo Sirainen ustream->read_fd = -1;
d74c9f4bf7ee37f3f58a895032ea013d07294865Timo Sirainen input = i_stream_create_file_common(&ustream->fstream, fd, NULL,
d74c9f4bf7ee37f3f58a895032ea013d07294865Timo Sirainen max_buffer_size, FALSE);
d74c9f4bf7ee37f3f58a895032ea013d07294865Timo Sirainen input->real_stream->iostream.close = i_stream_unix_close;
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen input->real_stream->read = i_stream_unix_read;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen return input;
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen}
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen
af81f402ddc897c74c1e85abd02879612ce44882Timo Sirainenvoid i_stream_unix_set_read_fd(struct istream *input)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen{
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen struct unix_istream *ustream =
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen (struct unix_istream *)input->real_stream;
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen ustream->next_read_fd = TRUE;
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen}
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen
9e095dd6a77097356aca8216356d4d71ef1bea45Timo Sirainenvoid i_stream_unix_unset_read_fd(struct istream *input)
9e095dd6a77097356aca8216356d4d71ef1bea45Timo Sirainen{
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen struct unix_istream *ustream =
9e095dd6a77097356aca8216356d4d71ef1bea45Timo Sirainen (struct unix_istream *)input->real_stream;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen ustream->next_read_fd = FALSE;
d74c9f4bf7ee37f3f58a895032ea013d07294865Timo Sirainen}
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenint i_stream_unix_get_read_fd(struct istream *input)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen{
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen struct unix_istream *ustream =
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen (struct unix_istream *)input->real_stream;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen int fd;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
d74c9f4bf7ee37f3f58a895032ea013d07294865Timo Sirainen fd = ustream->read_fd;
d74c9f4bf7ee37f3f58a895032ea013d07294865Timo Sirainen ustream->read_fd = -1;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen return fd;
b3142c8e513bc78da821fa70f479016148fa95e5Timo Sirainen}
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen