istream-concat.c revision 948b838c8e9896132e3a2d802fb5dad37e8dc716
/* Copyright (c) 2007-2016 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "buffer.h"
#include "istream-private.h"
#include "istream-concat.h"
struct concat_istream {
struct istream_private istream;
unsigned int cur_idx, unknown_size_idx;
};
bool close_parent)
{
unsigned int i;
/* get the parent streams to the wanted offset */
(void)i_stream_concat_skip(cstream);
}
if (close_parent) {
}
}
{
unsigned int i;
}
static void
{
unsigned int i;
}
{
const unsigned char *data;
if (cstream->prev_stream_skip != 0) {
cstream->prev_stream_skip = 0;
}
/* all the pending data is already in w_buffer */
return;
}
/* we already verified that the data size is less than the
maximum buffer size */
if (data_size > 0) {
i_unreached();
}
}
{
if (cstream->prev_stream_left == 0) {
/* no need to worry about buffers, skip everything */
/* we're still skipping inside buffer */
bytes_skipped = 0;
} else {
/* done with the buffer */
cstream->prev_stream_skip = 0;
cstream->prev_stream_left = 0;
}
}
{
const unsigned char *data;
bool last_stream;
if (data_size > cur_data_pos)
ret = 0;
else {
/* need to read more */
return ret;
"read(%s) failed: %s",
return -1;
}
/* we either read something or we're at EOF */
return -2;
return i_stream_concat_read(stream);
}
}
if (cstream->prev_stream_left == 0) {
/* we can point directly to the current stream's buffers */
} else if (data_size == cur_data_pos) {
/* nothing new read */
} else {
/* we still have some of the previous stream left. merge the
new data with it. */
return -2;
}
/* we'll copy all the new input to w_buffer. if we skip over
prev_stream_left bytes, the next read will switch to
pointing to cur_input's data directly. */
if (new_bytes_count > size)
}
(ret == 0 ? 0 : -1);
return ret;
}
static int
unsigned int *idx_r)
{
unsigned int i;
if (*v_offset == 0) {
/* seek to beginning of this stream */
break;
}
if (i == cstream->unknown_size_idx) {
/* we'll need to figure out this stream's size */
"stat(%s) failed: %s",
i_error("istream-concat: stat(%s) failed: %s",
return -1;
}
/* @UNSAFE */
}
break;
}
*idx_r = i;
return 0;
}
{
cstream->prev_stream_left = 0;
cstream->prev_stream_skip = 0;
/* failed */
return;
}
/* we allow seeking to EOF, but not past it. */
if (v_offset != 0) {
return;
}
}
}
static int
{
unsigned int i, cur_idx;
/* make sure we have all sizes */
return -1;
for (i = 0; i < cstream->unknown_size_idx; i++)
return 0;
}
{
struct concat_istream *cstream;
unsigned int count;
/* if any of the streams isn't blocking or seekable, set ourself also
if (cur_max > max_buffer_size)
}
}