istream.c revision c06f4017027263cf3a08becc551f5126409e2a83
e59faf65ce864fe95dc00f5d52b8323cdbd0608aTimo Sirainen/* Copyright (c) 2002-2003 Timo Sirainen */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen#include "lib.h"
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen#include "ioloop.h"
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen#include "str.h"
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen#include "istream-internal.h"
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenvoid i_stream_destroy(struct istream **stream)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen{
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen i_stream_close(*stream);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen i_stream_unref(stream);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen}
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
9955f6cba7652469b1d600a3674e8d27dd4e61bdTimo Sirainenvoid i_stream_ref(struct istream *stream)
9955f6cba7652469b1d600a3674e8d27dd4e61bdTimo Sirainen{
9955f6cba7652469b1d600a3674e8d27dd4e61bdTimo Sirainen _io_stream_ref(&stream->real_stream->iostream);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen}
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenvoid i_stream_unref(struct istream **stream)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen{
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct _istream *_stream = (*stream)->real_stream;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (_stream->iostream.refcount == 1) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (_stream->line_str != NULL)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen str_free(&_stream->line_str);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen }
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen _io_stream_unref(&(*stream)->real_stream->iostream);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen *stream = NULL;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen}
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenint i_stream_get_fd(struct istream *stream)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen{
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct _istream *_stream = stream->real_stream;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
d22301419109ed4a38351715e6760011421dadecTimo Sirainen return _stream->fd;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen}
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenvoid i_stream_close(struct istream *stream)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen{
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen _io_stream_close(&stream->real_stream->iostream);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen stream->closed = TRUE;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen}
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenvoid i_stream_set_max_buffer_size(struct istream *stream, size_t max_size)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen{
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen _io_stream_set_max_buffer_size(&stream->real_stream->iostream,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen max_size);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen}
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenssize_t i_stream_read(struct istream *stream)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen{
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct _istream *_stream = stream->real_stream;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (stream->closed)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return -1;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen stream->eof = FALSE;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return _stream->read(_stream);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen}
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenvoid i_stream_skip(struct istream *stream, uoff_t count)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen{
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct _istream *_stream = stream->real_stream;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen size_t data_size;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen data_size = _stream->pos - _stream->skip;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (count <= data_size) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* within buffer */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen stream->v_offset += count;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen _stream->skip += count;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen }
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* have to seek forward */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen count -= data_size;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen _stream->skip = _stream->pos;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen stream->v_offset += data_size;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (stream->closed)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen _stream->seek(_stream, stream->v_offset + count, FALSE);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen}
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenvoid i_stream_seek(struct istream *stream, uoff_t v_offset)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen{
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct _istream *_stream = stream->real_stream;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
d22301419109ed4a38351715e6760011421dadecTimo Sirainen if (v_offset >= stream->v_offset) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen i_stream_skip(stream, v_offset - stream->v_offset);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen }
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (stream->closed)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen stream->eof = FALSE;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen _stream->seek(_stream, v_offset, FALSE);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen}
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenvoid i_stream_seek_mark(struct istream *stream, uoff_t v_offset)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen{
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct _istream *_stream = stream->real_stream;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (stream->closed)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen stream->eof = FALSE;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen _stream->seek(_stream, v_offset, TRUE);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen}
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenvoid i_stream_sync(struct istream *stream)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen{
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct _istream *_stream = stream->real_stream;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (!stream->closed && _stream->sync != NULL)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen _stream->sync(_stream);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen}
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenconst struct stat *i_stream_stat(struct istream *stream, bool exact)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen{
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct _istream *_stream = stream->real_stream;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (stream->closed)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return NULL;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return _stream->stat(_stream, exact);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen}
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenbool i_stream_have_bytes_left(struct istream *stream)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen{
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct _istream *_stream = stream->real_stream;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return !stream->eof || _stream->skip != _stream->pos;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen}
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenstatic char *i_stream_next_line_finish(struct _istream *stream, size_t i)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen{
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen char *ret;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen size_t end;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (i > 0 && stream->buffer[i-1] == '\r')
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen end = i - 1;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen else
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen end = i;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (stream->w_buffer != NULL) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* modify the buffer directly */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen stream->w_buffer[end] = '\0';
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen ret = (char *)stream->w_buffer + stream->skip;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen } else {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* use a temporary string to return it */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (stream->line_str == NULL)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen stream->line_str = str_new(default_pool, 256);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen str_truncate(stream->line_str, 0);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen str_append_n(stream->line_str, stream->buffer + stream->skip,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen end - stream->skip);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen ret = str_c_modifiable(stream->line_str);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen }
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen i++;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen stream->istream.v_offset += i - stream->skip;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen stream->skip = i;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return ret;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen}
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenchar *i_stream_next_line(struct istream *stream)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen{
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct _istream *_stream = stream->real_stream;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen char *ret_buf;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen size_t i;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen i_assert(stream != NULL);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (_stream->skip >= _stream->pos) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen stream->stream_errno = 0;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen return NULL;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen }
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (_stream->w_buffer == NULL) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen i_error("i_stream_next_line() called for unmodifiable stream");
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return NULL;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen }
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* @UNSAFE */
d22301419109ed4a38351715e6760011421dadecTimo Sirainen ret_buf = NULL;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen for (i = _stream->skip; i < _stream->pos; i++) {
3f91e60401495a4046c73992fabaa5e77200a451Timo Sirainen if (_stream->buffer[i] == 10) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* got it */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen ret_buf = i_stream_next_line_finish(_stream, i);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen break;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen }
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen }
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return ret_buf;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen}
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
d22301419109ed4a38351715e6760011421dadecTimo Sirainenchar *i_stream_read_next_line(struct istream *stream)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen{
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen char *line;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen line = i_stream_next_line(stream);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (line != NULL)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return line;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
3f91e60401495a4046c73992fabaa5e77200a451Timo Sirainen if (i_stream_read(stream) > 0)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen line = i_stream_next_line(stream);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return line;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen}
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenconst unsigned char *i_stream_get_data(struct istream *stream, size_t *size_r)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen{
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct _istream *_stream = stream->real_stream;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
d22301419109ed4a38351715e6760011421dadecTimo Sirainen if (_stream->skip >= _stream->pos) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen *size_r = 0;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return NULL;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen }
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen *size_r = _stream->pos - _stream->skip;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen return _stream->buffer + _stream->skip;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen}
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenunsigned char *i_stream_get_modifiable_data(struct istream *stream,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen size_t *size_r)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen{
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct _istream *_stream = stream->real_stream;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (_stream->skip >= _stream->pos || _stream->w_buffer == NULL) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen *size_r = 0;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return NULL;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen }
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen *size_r = _stream->pos - _stream->skip;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return _stream->w_buffer + _stream->skip;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen}
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenint i_stream_read_data(struct istream *stream, const unsigned char **data_r,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen size_t *size_r, size_t threshold)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen{
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen ssize_t ret = 0;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen bool read_more = FALSE;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen do {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen *data_r = i_stream_get_data(stream, size_r);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (*size_r > threshold)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return 1;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* we need more data */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen ret = i_stream_read(stream);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (ret > 0)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen read_more = TRUE;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen } while (ret > 0);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen *data_r = i_stream_get_data(stream, size_r);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (ret == -2)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return -2;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (read_more || ret == 0) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen i_assert(!stream->blocking || stream->eof);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return 0;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen }
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return -1;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen}
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenstruct istream *_i_stream_create(struct _istream *_stream, pool_t pool, int fd,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen uoff_t abs_start_offset)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen{
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen _stream->fd = fd;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen _stream->abs_start_offset = abs_start_offset;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen _stream->istream.real_stream = _stream;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen memset(&_stream->statbuf, 0, sizeof(_stream->statbuf));
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen _stream->statbuf.st_size = -1;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen _stream->statbuf.st_atime =
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen _stream->statbuf.st_mtime =
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen _stream->statbuf.st_ctime = ioloop_time;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen _io_stream_init(pool, &_stream->iostream);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return &_stream->istream;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen}
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen#ifdef STREAM_TEST
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen/* gcc istream.c -o teststream liblib.a -Wall -DHAVE_CONFIG_H -DSTREAM_TEST -g */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen#include <fcntl.h>
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen#include <unistd.h>
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen#include "ostream.h"
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen#define BUF_VALUE(offset) \
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen (((offset) % 256) ^ ((offset) / 256))
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenstatic void check_buffer(const unsigned char *data, size_t size, size_t offset)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen{
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen size_t i;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen for (i = 0; i < size; i++)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen i_assert(data[i] == BUF_VALUE(i+offset));
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen}
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenint main(void)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen{
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct istream *input, *l_input;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct ostream *output1, *output2;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen int i, fd1, fd2;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen unsigned char buf[1024];
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen const unsigned char *data;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen size_t size;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen lib_init();
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen fd1 = open("teststream.1", O_RDWR | O_CREAT | O_TRUNC, 0600);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (fd1 < 0)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen i_fatal("open() failed: %m");
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen fd2 = open("teststream.2", O_RDWR | O_CREAT | O_TRUNC, 0600);
9955f6cba7652469b1d600a3674e8d27dd4e61bdTimo Sirainen if (fd2 < 0)
9955f6cba7652469b1d600a3674e8d27dd4e61bdTimo Sirainen i_fatal("open() failed: %m");
9955f6cba7652469b1d600a3674e8d27dd4e61bdTimo Sirainen
9955f6cba7652469b1d600a3674e8d27dd4e61bdTimo Sirainen /* write initial data */
9955f6cba7652469b1d600a3674e8d27dd4e61bdTimo Sirainen for (i = 0; i < sizeof(buf); i++)
9955f6cba7652469b1d600a3674e8d27dd4e61bdTimo Sirainen buf[i] = BUF_VALUE(i);
9955f6cba7652469b1d600a3674e8d27dd4e61bdTimo Sirainen write(fd1, buf, sizeof(buf));
9955f6cba7652469b1d600a3674e8d27dd4e61bdTimo Sirainen
9955f6cba7652469b1d600a3674e8d27dd4e61bdTimo Sirainen /* test reading */
9955f6cba7652469b1d600a3674e8d27dd4e61bdTimo Sirainen input = i_stream_create_file(fd1, default_pool, 512, FALSE);
9955f6cba7652469b1d600a3674e8d27dd4e61bdTimo Sirainen i_assert(i_stream_get_size(input) == sizeof(buf));
9955f6cba7652469b1d600a3674e8d27dd4e61bdTimo Sirainen
9955f6cba7652469b1d600a3674e8d27dd4e61bdTimo Sirainen i_assert(i_stream_read_data(input, &data, &size, 0) > 0);
9955f6cba7652469b1d600a3674e8d27dd4e61bdTimo Sirainen i_assert(size == 512);
9955f6cba7652469b1d600a3674e8d27dd4e61bdTimo Sirainen check_buffer(data, size, 0);
9955f6cba7652469b1d600a3674e8d27dd4e61bdTimo Sirainen
9955f6cba7652469b1d600a3674e8d27dd4e61bdTimo Sirainen i_stream_seek(input, 256);
9955f6cba7652469b1d600a3674e8d27dd4e61bdTimo Sirainen i_assert(i_stream_read_data(input, &data, &size, 0) > 0);
9955f6cba7652469b1d600a3674e8d27dd4e61bdTimo Sirainen i_assert(size == 512);
9955f6cba7652469b1d600a3674e8d27dd4e61bdTimo Sirainen check_buffer(data, size, 256);
9955f6cba7652469b1d600a3674e8d27dd4e61bdTimo Sirainen
9955f6cba7652469b1d600a3674e8d27dd4e61bdTimo Sirainen i_stream_seek(input, 0);
9955f6cba7652469b1d600a3674e8d27dd4e61bdTimo Sirainen i_assert(i_stream_read_data(input, &data, &size, 512) == -2);
9955f6cba7652469b1d600a3674e8d27dd4e61bdTimo Sirainen i_assert(size == 512);
9955f6cba7652469b1d600a3674e8d27dd4e61bdTimo Sirainen check_buffer(data, size, 0);
9955f6cba7652469b1d600a3674e8d27dd4e61bdTimo Sirainen
9955f6cba7652469b1d600a3674e8d27dd4e61bdTimo Sirainen i_stream_skip(input, 900);
9955f6cba7652469b1d600a3674e8d27dd4e61bdTimo Sirainen i_assert(i_stream_read_data(input, &data, &size, 0) > 0);
9955f6cba7652469b1d600a3674e8d27dd4e61bdTimo Sirainen i_assert(size == sizeof(buf) - 900);
9955f6cba7652469b1d600a3674e8d27dd4e61bdTimo Sirainen check_buffer(data, size, 900);
9955f6cba7652469b1d600a3674e8d27dd4e61bdTimo Sirainen
9955f6cba7652469b1d600a3674e8d27dd4e61bdTimo Sirainen /* test moving data */
9955f6cba7652469b1d600a3674e8d27dd4e61bdTimo Sirainen output1 = o_stream_create_file(fd1, default_pool, 512, FALSE);
9955f6cba7652469b1d600a3674e8d27dd4e61bdTimo Sirainen output2 = o_stream_create_file(fd2, default_pool, 512, FALSE);
9955f6cba7652469b1d600a3674e8d27dd4e61bdTimo Sirainen
9955f6cba7652469b1d600a3674e8d27dd4e61bdTimo Sirainen i_stream_seek(input, 1); size = sizeof(buf)-1;
9955f6cba7652469b1d600a3674e8d27dd4e61bdTimo Sirainen i_assert(o_stream_send_istream(output2, input) == size);
9955f6cba7652469b1d600a3674e8d27dd4e61bdTimo Sirainen o_stream_flush(output2);
9955f6cba7652469b1d600a3674e8d27dd4e61bdTimo Sirainen
9955f6cba7652469b1d600a3674e8d27dd4e61bdTimo Sirainen lseek(fd2, 0, SEEK_SET);
9955f6cba7652469b1d600a3674e8d27dd4e61bdTimo Sirainen i_assert(read(fd2, buf, sizeof(buf)) == size);
9955f6cba7652469b1d600a3674e8d27dd4e61bdTimo Sirainen check_buffer(buf, size, 1);
9955f6cba7652469b1d600a3674e8d27dd4e61bdTimo Sirainen
9955f6cba7652469b1d600a3674e8d27dd4e61bdTimo Sirainen i_stream_seek(input, 0);
9955f6cba7652469b1d600a3674e8d27dd4e61bdTimo Sirainen o_stream_seek(output1, sizeof(buf));
9955f6cba7652469b1d600a3674e8d27dd4e61bdTimo Sirainen i_assert(o_stream_send_istream(output1, input) == sizeof(buf));
9955f6cba7652469b1d600a3674e8d27dd4e61bdTimo Sirainen
9955f6cba7652469b1d600a3674e8d27dd4e61bdTimo Sirainen /* test moving with limits */
9955f6cba7652469b1d600a3674e8d27dd4e61bdTimo Sirainen l_input = i_stream_create_limit(default_pool, input,
9955f6cba7652469b1d600a3674e8d27dd4e61bdTimo Sirainen sizeof(buf)/2, 512);
9955f6cba7652469b1d600a3674e8d27dd4e61bdTimo Sirainen i_stream_seek(l_input, 0);
9955f6cba7652469b1d600a3674e8d27dd4e61bdTimo Sirainen o_stream_seek(output1, 10);
9955f6cba7652469b1d600a3674e8d27dd4e61bdTimo Sirainen i_assert(o_stream_send_istream(output1, l_input) == 512);
9955f6cba7652469b1d600a3674e8d27dd4e61bdTimo Sirainen
9955f6cba7652469b1d600a3674e8d27dd4e61bdTimo Sirainen i_stream_set_max_buffer_size(input, sizeof(buf));
9955f6cba7652469b1d600a3674e8d27dd4e61bdTimo Sirainen
9955f6cba7652469b1d600a3674e8d27dd4e61bdTimo Sirainen i_stream_seek(input, 0);
9955f6cba7652469b1d600a3674e8d27dd4e61bdTimo Sirainen i_assert(i_stream_read_data(input, &data, &size, sizeof(buf)-1) > 0);
9955f6cba7652469b1d600a3674e8d27dd4e61bdTimo Sirainen i_assert(size == sizeof(buf));
9955f6cba7652469b1d600a3674e8d27dd4e61bdTimo Sirainen check_buffer(data, 10, 0);
9955f6cba7652469b1d600a3674e8d27dd4e61bdTimo Sirainen check_buffer(data + 10, 512, sizeof(buf)/2);
9955f6cba7652469b1d600a3674e8d27dd4e61bdTimo Sirainen check_buffer(data + 10 + 512,
9955f6cba7652469b1d600a3674e8d27dd4e61bdTimo Sirainen size - (10 + 512), 10 + 512);
9955f6cba7652469b1d600a3674e8d27dd4e61bdTimo Sirainen
9955f6cba7652469b1d600a3674e8d27dd4e61bdTimo Sirainen /* reading within limits */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen i_stream_seek(l_input, 0);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen i_assert(i_stream_read_data(l_input, &data, &size, 511) > 0);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen i_assert(size == 512);
9955f6cba7652469b1d600a3674e8d27dd4e61bdTimo Sirainen i_assert(i_stream_read_data(l_input, &data, &size, 512) == -2);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen i_assert(size == 512);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen i_stream_skip(l_input, 511);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen i_assert(i_stream_read_data(l_input, &data, &size, 0) > 0);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen i_assert(size == 1);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen i_stream_skip(l_input, 1);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen i_assert(i_stream_read_data(l_input, &data, &size, 0) == -1);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen i_assert(size == 0);
9955f6cba7652469b1d600a3674e8d27dd4e61bdTimo Sirainen
9955f6cba7652469b1d600a3674e8d27dd4e61bdTimo Sirainen unlink("teststream.1");
9955f6cba7652469b1d600a3674e8d27dd4e61bdTimo Sirainen unlink("teststream.2");
9955f6cba7652469b1d600a3674e8d27dd4e61bdTimo Sirainen return 0;
9955f6cba7652469b1d600a3674e8d27dd4e61bdTimo Sirainen}
9955f6cba7652469b1d600a3674e8d27dd4e61bdTimo Sirainen#endif
9955f6cba7652469b1d600a3674e8d27dd4e61bdTimo Sirainen