istream.c revision 282a436a74d8835edb45cc019b1c916013013fd3
bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2002-2008 Dovecot authors, see the included COPYING file */
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi#include "lib.h"
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi#include "ioloop.h"
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi#include "str.h"
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi#include "istream-internal.h"
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomivoid i_stream_destroy(struct istream **stream)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi{
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi i_stream_close(*stream);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi i_stream_unref(stream);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi}
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomivoid i_stream_ref(struct istream *stream)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi{
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi io_stream_ref(&stream->real_stream->iostream);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi}
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomivoid i_stream_unref(struct istream **stream)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi{
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi struct istream_private *_stream = (*stream)->real_stream;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi if (_stream->iostream.refcount == 1) {
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi if (_stream->line_str != NULL)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi str_free(&_stream->line_str);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi }
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi io_stream_unref(&(*stream)->real_stream->iostream);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi *stream = NULL;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi}
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi#undef i_stream_set_destroy_callback
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomivoid i_stream_set_destroy_callback(struct istream *stream,
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi istream_callback_t *callback, void *context)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi{
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi struct iostream_private *iostream = &stream->real_stream->iostream;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi iostream->destroy_callback = callback;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi iostream->destroy_context = context;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi}
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomiint i_stream_get_fd(struct istream *stream)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi{
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi struct istream_private *_stream = stream->real_stream;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi return _stream->fd;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi}
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomivoid i_stream_close(struct istream *stream)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi{
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi io_stream_close(&stream->real_stream->iostream);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi stream->closed = TRUE;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi if (stream->stream_errno == 0)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi stream->stream_errno = ECONNRESET;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi}
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomivoid i_stream_set_max_buffer_size(struct istream *stream, size_t max_size)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi{
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi io_stream_set_max_buffer_size(&stream->real_stream->iostream, max_size);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi}
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomissize_t i_stream_read(struct istream *stream)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi{
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi struct istream_private *_stream = stream->real_stream;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi if (unlikely(stream->closed))
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi return -1;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi stream->eof = FALSE;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi return _stream->read(_stream);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi}
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomivoid i_stream_skip(struct istream *stream, uoff_t count)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi{
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi struct istream_private *_stream = stream->real_stream;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi size_t data_size;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
bf7dc750b95039981c0e9d728f313d50cf38a156Martti Rannanjärvi data_size = _stream->pos - _stream->skip;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi if (count <= data_size) {
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi /* within buffer */
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi stream->v_offset += count;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi _stream->skip += count;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi return;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi }
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi /* have to seek forward */
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi count -= data_size;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi _stream->skip = _stream->pos;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi stream->v_offset += data_size;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi if (unlikely(stream->closed))
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi return;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi _stream->seek(_stream, stream->v_offset + count, FALSE);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi}
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomistatic bool i_stream_can_optimize_seek(struct istream *stream)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi{
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi uoff_t expected_offset;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi if (stream->real_stream->parent == NULL)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi return TRUE;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi /* use the fast route only if the parent stream is at the
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi expected offset */
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi expected_offset = stream->real_stream->parent_start_offset +
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi stream->v_offset - stream->real_stream->skip;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi if (stream->real_stream->parent->v_offset != expected_offset)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi return FALSE;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi return i_stream_can_optimize_seek(stream->real_stream->parent);
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch}
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomivoid i_stream_seek(struct istream *stream, uoff_t v_offset)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi{
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi struct istream_private *_stream = stream->real_stream;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi if (v_offset >= stream->v_offset &&
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi i_stream_can_optimize_seek(stream)) {
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi i_stream_skip(stream, v_offset - stream->v_offset);
bf7dc750b95039981c0e9d728f313d50cf38a156Martti Rannanjärvi return;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi }
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi if (unlikely(stream->closed))
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi return;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi stream->eof = FALSE;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi _stream->seek(_stream, v_offset, FALSE);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi}
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomivoid i_stream_seek_mark(struct istream *stream, uoff_t v_offset)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi{
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi struct istream_private *_stream = stream->real_stream;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi if (unlikely(stream->closed))
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi return;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi stream->eof = FALSE;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi _stream->seek(_stream, v_offset, TRUE);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi}
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomivoid i_stream_sync(struct istream *stream)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi{
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi struct istream_private *_stream = stream->real_stream;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi if (unlikely(stream->closed))
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi return;
e98ba66a8ead146be66ba8219038a45fbf87b62cStephan Bosch
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi if (_stream->sync != NULL)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi _stream->sync(_stream);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi}
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomiconst struct stat *i_stream_stat(struct istream *stream, bool exact)
532bb6cdc2fc62ae39ed51a694528852c2da9e07Aki Tuomi{
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi struct istream_private *_stream = stream->real_stream;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi if (unlikely(stream->closed))
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi return NULL;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi return _stream->stat(_stream, exact);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi}
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomibool i_stream_have_bytes_left(const struct istream *stream)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi{
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi const struct istream_private *_stream = stream->real_stream;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi return !stream->eof || _stream->skip != _stream->pos;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi}
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomistatic char *i_stream_next_line_finish(struct istream_private *stream, size_t i)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi{
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi char *ret;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi size_t end;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi if (i > 0 && stream->buffer[i-1] == '\r')
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi end = i - 1;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi else
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi end = i;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi if (stream->w_buffer != NULL) {
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi /* modify the buffer directly */
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi stream->w_buffer[end] = '\0';
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi ret = (char *)stream->w_buffer + stream->skip;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi } else {
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi /* use a temporary string to return it */
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi if (stream->line_str == NULL)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi stream->line_str = str_new(default_pool, 256);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi str_truncate(stream->line_str, 0);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi str_append_n(stream->line_str, stream->buffer + stream->skip,
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi end - stream->skip);
eb318ea05532d2e54ed3bfc89bc15dcf1adae838Timo Sirainen ret = str_c_modifiable(stream->line_str);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi }
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi i++;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi stream->istream.v_offset += i - stream->skip;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi stream->skip = i;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi return ret;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi}
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomichar *i_stream_next_line(struct istream *stream)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi{
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi struct istream_private *_stream = stream->real_stream;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi char *ret_buf;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi size_t i;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi if (_stream->skip >= _stream->pos) {
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi stream->stream_errno = 0;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi return NULL;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi }
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi if (unlikely(_stream->w_buffer == NULL)) {
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi i_error("i_stream_next_line() called for unmodifiable stream");
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi return NULL;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi }
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi /* @UNSAFE */
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi ret_buf = NULL;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi for (i = _stream->skip; i < _stream->pos; i++) {
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi if (_stream->buffer[i] == 10) {
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi /* got it */
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi ret_buf = i_stream_next_line_finish(_stream, i);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi break;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi }
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi }
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi return ret_buf;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi}
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomichar *i_stream_read_next_line(struct istream *stream)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi{
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi char *line;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi for (;;) {
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi line = i_stream_next_line(stream);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi if (line != NULL)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi break;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi if (i_stream_read(stream) <= 0)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi return NULL;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi }
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi return line;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi}
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomiconst unsigned char *
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomii_stream_get_data(const struct istream *stream, size_t *size_r)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi{
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi const struct istream_private *_stream = stream->real_stream;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi if (_stream->skip >= _stream->pos) {
bf2d54df4f5943ec0617aadb1900bb8f40b12150Aki Tuomi *size_r = 0;
bf2d54df4f5943ec0617aadb1900bb8f40b12150Aki Tuomi return NULL;
bf7dc750b95039981c0e9d728f313d50cf38a156Martti Rannanjärvi }
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi *size_r = _stream->pos - _stream->skip;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi return _stream->buffer + _stream->skip;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi}
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomiunsigned char *i_stream_get_modifiable_data(const struct istream *stream,
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi size_t *size_r)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi{
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi const struct istream_private *_stream = stream->real_stream;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi if (_stream->skip >= _stream->pos || _stream->w_buffer == NULL) {
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi *size_r = 0;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi return NULL;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi }
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi *size_r = _stream->pos - _stream->skip;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi return _stream->w_buffer + _stream->skip;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi}
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomiint i_stream_read_data(struct istream *stream, const unsigned char **data_r,
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi size_t *size_r, size_t threshold)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi{
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi ssize_t ret = 0;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi bool read_more = FALSE;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi do {
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi *data_r = i_stream_get_data(stream, size_r);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi if (*size_r > threshold)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi return 1;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi /* we need more data */
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi ret = i_stream_read(stream);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi if (ret > 0)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi read_more = TRUE;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi } while (ret > 0);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi *data_r = i_stream_get_data(stream, size_r);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi if (ret == -2)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi return -2;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi if (read_more || ret == 0) {
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi i_assert(!stream->blocking || stream->eof);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi return 0;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi }
5d7fe1420add7667840a81445bc261d2cae1938cTimo Sirainen return -1;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi}
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomivoid i_stream_compress(struct istream_private *stream)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi{
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi memmove(stream->w_buffer, stream->w_buffer + stream->skip,
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi stream->pos - stream->skip);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi stream->pos -= stream->skip;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi stream->skip = 0;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi}
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomivoid i_stream_grow_buffer(struct istream_private *stream, size_t bytes)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi{
bf2d54df4f5943ec0617aadb1900bb8f40b12150Aki Tuomi size_t old_size;
bf2d54df4f5943ec0617aadb1900bb8f40b12150Aki Tuomi
bf7dc750b95039981c0e9d728f313d50cf38a156Martti Rannanjärvi old_size = stream->buffer_size;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi stream->buffer_size = stream->pos + bytes;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi if (stream->buffer_size <= I_STREAM_MIN_SIZE)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi stream->buffer_size = I_STREAM_MIN_SIZE;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi else
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi stream->buffer_size = nearest_power(stream->buffer_size);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi if (stream->max_buffer_size > 0 &&
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi stream->buffer_size > stream->max_buffer_size)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi stream->buffer_size = stream->max_buffer_size;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi stream->buffer = stream->w_buffer =
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi i_realloc(stream->w_buffer, old_size, stream->buffer_size);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi}
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomibool i_stream_get_buffer_space(struct istream_private *stream,
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi size_t wanted_size, size_t *size_r)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi{
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi i_assert(wanted_size > 0);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi if (wanted_size > stream->buffer_size - stream->pos) {
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi if (stream->skip > 0) {
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi /* remove the unused bytes from beginning of buffer */
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi i_stream_compress(stream);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi } else if (stream->max_buffer_size == 0 ||
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi stream->buffer_size < stream->max_buffer_size) {
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi /* buffer is full - grow it */
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi i_stream_grow_buffer(stream, I_STREAM_MIN_SIZE);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi }
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi }
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi if (size_r != NULL)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi *size_r = stream->buffer_size - stream->pos;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi return stream->pos != stream->buffer_size;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi}
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomibool i_stream_add_data(struct istream *_stream, const unsigned char *data,
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi size_t size)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi{
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi struct istream_private *stream = _stream->real_stream;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi size_t size2;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi (void)i_stream_get_buffer_space(stream, size, &size2);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi if (size > size2)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi return FALSE;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi memcpy(stream->w_buffer + stream->pos, data, size);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi stream->pos += size;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi return TRUE;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi}
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomistatic void
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomii_stream_default_set_max_buffer_size(struct iostream_private *stream,
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi size_t max_size)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi{
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi struct istream_private *_stream = (struct istream_private *)stream;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi _stream->max_buffer_size = max_size;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi}
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomistatic const struct stat *
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomii_stream_default_stat(struct istream_private *stream, bool exact ATTR_UNUSED)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi{
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi return &stream->statbuf;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi}
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomistruct istream *
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomii_stream_create(struct istream_private *_stream, struct istream *parent, int fd)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi{
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi _stream->fd = fd;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi if (parent != NULL) {
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi _stream->parent = parent;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi _stream->parent_start_offset = parent->v_offset;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi _stream->abs_start_offset = parent->v_offset +
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi parent->real_stream->abs_start_offset;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi }
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi _stream->istream.real_stream = _stream;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi if (_stream->stat == NULL)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi _stream->stat = i_stream_default_stat;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi if (_stream->iostream.set_max_buffer_size == NULL) {
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi _stream->iostream.set_max_buffer_size =
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi i_stream_default_set_max_buffer_size;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi }
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi memset(&_stream->statbuf, 0, sizeof(_stream->statbuf));
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi _stream->statbuf.st_size = -1;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi _stream->statbuf.st_atime =
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi _stream->statbuf.st_mtime =
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi _stream->statbuf.st_ctime = ioloop_time;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi io_stream_init(&_stream->iostream);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi return &_stream->istream;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi}
bf2d54df4f5943ec0617aadb1900bb8f40b12150Aki Tuomi
bf2d54df4f5943ec0617aadb1900bb8f40b12150Aki Tuomi#ifdef STREAM_TEST
bf7dc750b95039981c0e9d728f313d50cf38a156Martti Rannanjärvi/* gcc istream.c -o teststream liblib.a -Wall -DHAVE_CONFIG_H -DSTREAM_TEST -g */
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
0dab9cb35a976c49b28a11e28d5570f5191f1a7aMartti Rannanjärvi#include <fcntl.h>
0dab9cb35a976c49b28a11e28d5570f5191f1a7aMartti Rannanjärvi#include <unistd.h>
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi#include "ostream.h"
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi#define BUF_VALUE(offset) \
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi (((offset) % 256) ^ ((offset) / 256))
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomistatic void check_buffer(const unsigned char *data, size_t size, size_t offset)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi{
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi size_t i;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi for (i = 0; i < size; i++)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi i_assert(data[i] == BUF_VALUE(i+offset));
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi}
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomiint main(void)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi{
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi struct istream *input, *l_input;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi struct ostream *output1, *output2;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi int i, fd1, fd2;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi unsigned char buf[1024];
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi const unsigned char *data;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi size_t size;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
c147bff818798a979d93537f72f5c1f68f5d5ba8Aki Tuomi lib_init();
b261fc7c4fa222748c8c4e401d925d32e0d86041Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi fd1 = open("teststream.1", O_RDWR | O_CREAT | O_TRUNC, 0600);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi if (fd1 < 0)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi i_fatal("open() failed: %m");
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi fd2 = open("teststream.2", O_RDWR | O_CREAT | O_TRUNC, 0600);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi if (fd2 < 0)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi i_fatal("open() failed: %m");
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi /* write initial data */
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi for (i = 0; i < sizeof(buf); i++)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi buf[i] = BUF_VALUE(i);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi write(fd1, buf, sizeof(buf));
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi /* test reading */
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi input = i_stream_create_fd(fd1, 512, FALSE);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi i_assert(i_stream_get_size(input) == sizeof(buf));
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
beec8b0a6a3ece557c9acec524e82542a9641662Aki Tuomi i_assert(i_stream_read_data(input, &data, &size, 0) > 0);
beec8b0a6a3ece557c9acec524e82542a9641662Aki Tuomi i_assert(size == 512);
beec8b0a6a3ece557c9acec524e82542a9641662Aki Tuomi check_buffer(data, size, 0);
beec8b0a6a3ece557c9acec524e82542a9641662Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi i_stream_seek(input, 256);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi i_assert(i_stream_read_data(input, &data, &size, 0) > 0);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi i_assert(size == 512);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi check_buffer(data, size, 256);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi i_stream_seek(input, 0);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi i_assert(i_stream_read_data(input, &data, &size, 512) == -2);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi i_assert(size == 512);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi check_buffer(data, size, 0);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi i_stream_skip(input, 900);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi i_assert(i_stream_read_data(input, &data, &size, 0) > 0);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi i_assert(size == sizeof(buf) - 900);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi check_buffer(data, size, 900);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi /* test moving data */
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi output1 = o_stream_create_fd(fd1, 512, FALSE);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi output2 = o_stream_create_fd(fd2, 512, FALSE);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi i_stream_seek(input, 1); size = sizeof(buf)-1;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi i_assert(o_stream_send_istream(output2, input) == size);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi o_stream_flush(output2);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi lseek(fd2, 0, SEEK_SET);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi i_assert(read(fd2, buf, sizeof(buf)) == size);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi check_buffer(buf, size, 1);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi i_stream_seek(input, 0);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi o_stream_seek(output1, sizeof(buf));
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi i_assert(o_stream_send_istream(output1, input) == sizeof(buf));
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi /* test moving with limits */
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi l_input = i_stream_create_limit(input, sizeof(buf)/2, 512);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi i_stream_seek(l_input, 0);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi o_stream_seek(output1, 10);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi i_assert(o_stream_send_istream(output1, l_input) == 512);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi i_stream_set_max_buffer_size(input, sizeof(buf));
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi i_stream_seek(input, 0);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi i_assert(i_stream_read_data(input, &data, &size, sizeof(buf)-1) > 0);
i_assert(size == sizeof(buf));
check_buffer(data, 10, 0);
check_buffer(data + 10, 512, sizeof(buf)/2);
check_buffer(data + 10 + 512,
size - (10 + 512), 10 + 512);
/* reading within limits */
i_stream_seek(l_input, 0);
i_assert(i_stream_read_data(l_input, &data, &size, 511) > 0);
i_assert(size == 512);
i_assert(i_stream_read_data(l_input, &data, &size, 512) == -2);
i_assert(size == 512);
i_stream_skip(l_input, 511);
i_assert(i_stream_read_data(l_input, &data, &size, 0) > 0);
i_assert(size == 1);
i_stream_skip(l_input, 1);
i_assert(i_stream_read_data(l_input, &data, &size, 0) == -1);
i_assert(size == 0);
unlink("teststream.1");
unlink("teststream.2");
return 0;
}
#endif