istream-try.c revision 2974dca6be5120e49279f06c8aa952e5fac56048
5e0ce63bb65db34d7f48b34bbb5545fa791781c4Timo Sirainen/* Copyright (c) 2013-2017 Dovecot authors, see the included COPYING file */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen unsigned int try_idx;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenstatic void i_stream_unref_try_inputs(struct try_istream *tstream)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen for (unsigned int i = 0; i < tstream->try_input_count; i++) {
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainenstatic void i_stream_try_close(struct iostream_private *stream,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen struct try_istream *tstream = (struct try_istream *)stream;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen for (unsigned int i = 0; i < tstream->try_input_count; i++) {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenstatic bool i_stream_try_is_buffer_full(struct istream *try_input)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen /* See if one of the parent istreams have their buffer full.
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen This is mainly intended to check with istream-tee whether its
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen parent is full. That means that the try_input has already seen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen a full buffer of input, but it hasn't decided to return anything
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen yet. But it also hasn't failed, so we'll assume that the input is
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen correct for it and it simply needs a lot more input before it can
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen return anything (e.g. istream-bzlib). */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen while (try_input->real_stream->parent != NULL) {
01af88dfbb7a022ddb3ab9fb4159f2a4a204ead3Timo Sirainen if (try_input->real_stream->pos == try_input->real_stream->buffer_size &&
01af88dfbb7a022ddb3ab9fb4159f2a4a204ead3Timo Sirainenstatic int i_stream_try_detect(struct try_istream *tstream)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen for (; tstream->try_idx < tstream->try_input_count; tstream->try_idx++) {
01af88dfbb7a022ddb3ab9fb4159f2a4a204ead3Timo Sirainen if (ret == 0 && i_stream_try_is_buffer_full(try_input))
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen i_stream_init_parent(&tstream->istream, try_input);
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen io_stream_set_error(&tstream->istream.iostream,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen "Unexpected error while detecting stream format: %s",
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen /* All streams failed with EINVAL. */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen io_stream_set_error(&tstream->istream.iostream,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen "Failed to detect stream format");
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen tstream->istream.istream.stream_errno = EINVAL;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Siraineni_stream_try_read(struct istream_private *stream)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen struct try_istream *tstream = (struct try_istream *)stream;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if ((ret = i_stream_try_detect(tstream)) <= 0)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen i_stream_seek(stream->parent, stream->parent_start_offset +
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen return i_stream_read_copy_from_parent(&stream->istream);
1060afdc2fcdf647dbb3bc11647401f1b44a3a8aTimo Sirainenstruct istream *istream_try_create(struct istream *const input[])
1060afdc2fcdf647dbb3bc11647401f1b44a3a8aTimo Sirainen unsigned int count;
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen for (count = 0; input[count] != NULL; count++) {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen tstream->try_input = p_memdup(default_pool, input,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen tstream->istream.iostream.close = i_stream_try_close;
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen tstream->istream.max_buffer_size = max_buffer_size;
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen return i_stream_create(&tstream->istream, NULL, -1, 0);