istream.c revision 5a9bbcb13b2dd2cf9a825c7ed09fe7ee143b1275
2e37d45867d081db150ab78dad303b9077aea24fTimo Sirainen/* Copyright (c) 2002-2018 Dovecot authors, see the included COPYING file */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include "lib.h"
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include "ioloop.h"
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen#include "array.h"
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include "str.h"
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include "memarea.h"
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen#include "istream-private.h"
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainenstatic bool i_stream_is_buffer_invalid(const struct istream_private *stream);
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainenvoid i_stream_set_name(struct istream *stream, const char *name)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen{
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen i_free(stream->real_stream->iostream.name);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen stream->real_stream->iostream.name = i_strdup(name);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen}
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainenconst char *i_stream_get_name(struct istream *stream)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen{
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen while (stream->real_stream->iostream.name == NULL) {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen stream = stream->real_stream->parent;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (stream == NULL)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return "";
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen }
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return stream->real_stream->iostream.name;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen}
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenstatic void i_stream_close_full(struct istream *stream, bool close_parents)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen{
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen io_stream_close(&stream->real_stream->iostream, close_parents);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen stream->closed = TRUE;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (stream->stream_errno == 0)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen stream->stream_errno = EPIPE;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen}
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainenvoid i_stream_destroy(struct istream **stream)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen{
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (*stream == NULL)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen i_stream_close_full(*stream, FALSE);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen i_stream_unref(stream);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen}
939a0d82523538b2de38a02bc9f790a67b7ebf47Timo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenvoid i_stream_ref(struct istream *stream)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen{
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen io_stream_ref(&stream->real_stream->iostream);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen}
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenvoid i_stream_unref(struct istream **stream)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen{
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen struct istream_private *_stream;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (*stream == NULL)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen _stream = (*stream)->real_stream;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (!io_stream_unref(&_stream->iostream)) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen str_free(&_stream->line_str);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen i_stream_snapshot_free(&_stream->prev_snapshot);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen i_stream_unref(&_stream->parent);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen io_stream_free(&_stream->iostream);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen }
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen *stream = NULL;
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen}
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen#undef i_stream_add_destroy_callback
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenvoid i_stream_add_destroy_callback(struct istream *stream,
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen istream_callback_t *callback, void *context)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen{
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen io_stream_add_destroy_callback(&stream->real_stream->iostream,
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen callback, context);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen}
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainenvoid i_stream_remove_destroy_callback(struct istream *stream,
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen void (*callback)())
84ed9f8f3d0e5ed47607ef417618e49e4f865557Timo Sirainen{
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen io_stream_remove_destroy_callback(&stream->real_stream->iostream,
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen callback);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen}
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenint i_stream_get_fd(struct istream *stream)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen{
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen struct istream_private *_stream = stream->real_stream;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return _stream->fd;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen}
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenconst char *i_stream_get_error(struct istream *stream)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen{
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen struct istream *s;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen /* we'll only return errors for streams that have stream_errno set or
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen that have reached EOF. we might be returning unintended error
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen otherwise. */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (stream->stream_errno == 0)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen return stream->eof ? "EOF" : "<no error>";
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen for (s = stream; s != NULL; s = s->real_stream->parent) {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (s->stream_errno == 0)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen break;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (s->real_stream->iostream.error != NULL)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen return s->real_stream->iostream.error;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen }
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return strerror(stream->stream_errno);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen}
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainenconst char *i_stream_get_disconnect_reason(struct istream *stream)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen{
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen return io_stream_get_disconnect_reason(stream, NULL);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen}
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainenvoid i_stream_close(struct istream *stream)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen{
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (stream != NULL)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen i_stream_close_full(stream, TRUE);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen}
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenvoid i_stream_set_init_buffer_size(struct istream *stream, size_t size)
c9dea5c23355dea35c6fa423de69f6507852efe4Timo Sirainen{
c9dea5c23355dea35c6fa423de69f6507852efe4Timo Sirainen stream->real_stream->init_buffer_size = size;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen}
7a24bdc1a5e2d5368c2569b4852192f2bdb5a31fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainenvoid i_stream_set_max_buffer_size(struct istream *stream, size_t max_size)
7a24bdc1a5e2d5368c2569b4852192f2bdb5a31fTimo Sirainen{
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen io_stream_set_max_buffer_size(&stream->real_stream->iostream, max_size);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen}
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainensize_t i_stream_get_max_buffer_size(struct istream *stream)
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen{
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen size_t max_size = 0;
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen do {
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen if (max_size < stream->real_stream->max_buffer_size)
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen max_size = stream->real_stream->max_buffer_size;
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen stream = stream->real_stream->parent;
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen } while (stream != NULL);
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen return max_size;
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen}
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen
d22301419109ed4a38351715e6760011421dadecTimo Sirainenvoid i_stream_set_return_partial_line(struct istream *stream, bool set)
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen{
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen stream->real_stream->return_nolf_line = set;
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen}
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainenvoid i_stream_set_persistent_buffers(struct istream *stream, bool set)
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen{
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen do {
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen stream->real_stream->nonpersistent_buffers = !set;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen stream = stream->real_stream->parent;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen } while (stream != NULL);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen}
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainenvoid i_stream_set_blocking(struct istream *stream, bool blocking)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen{
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen int prev_fd = -1;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen do {
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen stream->blocking = blocking;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (stream->real_stream->fd != -1 &&
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen stream->real_stream->fd != prev_fd) {
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen fd_set_nonblock(stream->real_stream->fd, !blocking);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen prev_fd = stream->real_stream->fd;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen }
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen stream = stream->real_stream->parent;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen } while (stream != NULL);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen}
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
6d6c1517ef20e340a3aace406724fc8916f2d13fTimo Sirainenstatic void i_stream_update(struct istream_private *stream)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen{
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (stream->parent == NULL)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen stream->access_counter++;
7e209b78ca757294dbbc15604c88673b3a6b0c39Timo Sirainen else {
7e209b78ca757294dbbc15604c88673b3a6b0c39Timo Sirainen stream->access_counter =
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen stream->parent->real_stream->access_counter;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen stream->parent_expected_offset = stream->parent->v_offset;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen }
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen}
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainenstatic bool snapshot_has_memarea(struct istream_snapshot *snapshot,
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen struct memarea *memarea)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen{
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (snapshot->old_memarea == memarea)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen return TRUE;
939a0d82523538b2de38a02bc9f790a67b7ebf47Timo Sirainen if (snapshot->prev_snapshot != NULL)
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen return snapshot_has_memarea(snapshot->prev_snapshot, memarea);
939a0d82523538b2de38a02bc9f790a67b7ebf47Timo Sirainen return FALSE;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen}
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainenstruct istream_snapshot *
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Siraineni_stream_default_snapshot(struct istream_private *stream,
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen struct istream_snapshot *prev_snapshot)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen{
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen struct istream_snapshot *snapshot;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (stream->memarea != NULL) {
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (prev_snapshot != NULL) {
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (snapshot_has_memarea(prev_snapshot, stream->memarea))
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen return prev_snapshot;
939a0d82523538b2de38a02bc9f790a67b7ebf47Timo Sirainen }
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen /* This stream has a memarea. Reference it, so we can later on
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen rollback if needed. */
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen snapshot = i_new(struct istream_snapshot, 1);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen snapshot->old_memarea = stream->memarea;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen snapshot->prev_snapshot = prev_snapshot;
939a0d82523538b2de38a02bc9f790a67b7ebf47Timo Sirainen memarea_ref(snapshot->old_memarea);
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen return snapshot;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen }
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (stream->parent == NULL) {
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (stream->nonpersistent_buffers) {
939a0d82523538b2de38a02bc9f790a67b7ebf47Timo Sirainen /* Assume that memarea would be used normally, but
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen now it's NULL because the buffer is empty and
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen empty buffers are freed. */
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen i_assert(stream->skip == stream->pos);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen return prev_snapshot;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen }
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen i_panic("%s is missing istream.snapshot() implementation",
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen i_stream_get_name(&stream->istream));
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen }
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen struct istream_private *_parent_stream =
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen stream->parent->real_stream;
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen return _parent_stream->snapshot(_parent_stream, prev_snapshot);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen}
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainenvoid i_stream_snapshot_free(struct istream_snapshot **_snapshot)
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen{
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen struct istream_snapshot *snapshot = *_snapshot;
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen if (*_snapshot == NULL)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen return;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen *_snapshot = NULL;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
6d6c1517ef20e340a3aace406724fc8916f2d13fTimo Sirainen i_stream_snapshot_free(&snapshot->prev_snapshot);
6d6c1517ef20e340a3aace406724fc8916f2d13fTimo Sirainen if (snapshot->old_memarea != NULL)
6d6c1517ef20e340a3aace406724fc8916f2d13fTimo Sirainen memarea_unref(&snapshot->old_memarea);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen i_free(snapshot);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen}
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainenstatic struct istream_snapshot *
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Siraineni_stream_noop_snapshot(struct istream_private *stream ATTR_UNUSED,
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen struct istream_snapshot *prev_snapshot)
939a0d82523538b2de38a02bc9f790a67b7ebf47Timo Sirainen{
939a0d82523538b2de38a02bc9f790a67b7ebf47Timo Sirainen return prev_snapshot;
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen}
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
939a0d82523538b2de38a02bc9f790a67b7ebf47Timo Sirainenssize_t i_stream_read(struct istream *stream)
939a0d82523538b2de38a02bc9f790a67b7ebf47Timo Sirainen{
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen struct istream_private *_stream = stream->real_stream;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen ssize_t ret;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen#ifdef DEBUG
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen unsigned char prev_buf[4];
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen const unsigned char *prev_data = _stream->buffer;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen size_t prev_skip = _stream->skip, prev_pos = _stream->pos;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen bool invalid = i_stream_is_buffer_invalid(_stream);
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen i_assert(prev_skip <= prev_pos);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (invalid)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen ;
c9dea5c23355dea35c6fa423de69f6507852efe4Timo Sirainen else if (prev_pos - prev_skip <= 4)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen memcpy(prev_buf, prev_data + prev_skip, prev_pos - prev_skip);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen else {
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen memcpy(prev_buf, prev_data + prev_skip, 2);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen memcpy(prev_buf+2, prev_data + prev_pos - 2, 2);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen }
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen#endif
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen _stream->prev_snapshot =
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen _stream->snapshot(_stream, _stream->prev_snapshot);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen ret = i_stream_read_memarea(stream);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (ret > 0)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen i_stream_snapshot_free(&_stream->prev_snapshot);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen#ifdef DEBUG
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen else if (!invalid) {
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen i_assert((_stream->pos - _stream->skip) == (prev_pos - prev_skip));
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (prev_pos - prev_skip <= 4)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen i_assert(memcmp(prev_buf, prev_data + prev_skip, prev_pos - prev_skip) == 0);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen else {
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen i_assert(memcmp(prev_buf, prev_data + prev_skip, 2) == 0);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen i_assert(memcmp(prev_buf+2, prev_data + prev_pos - 2, 2) == 0);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen }
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen }
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen#endif
7e209b78ca757294dbbc15604c88673b3a6b0c39Timo Sirainen return ret;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen}
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainenssize_t i_stream_read_memarea(struct istream *stream)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen{
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen struct istream_private *_stream = stream->real_stream;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen size_t old_size;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen ssize_t ret;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (unlikely(stream->closed || stream->stream_errno != 0)) {
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen stream->eof = TRUE;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen errno = stream->stream_errno;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen return -1;
6d6c1517ef20e340a3aace406724fc8916f2d13fTimo Sirainen }
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen stream->eof = FALSE;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (_stream->parent != NULL)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen i_stream_seek(_stream->parent, _stream->parent_expected_offset);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen old_size = _stream->pos - _stream->skip;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen ret = _stream->read(_stream);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen i_assert(old_size <= _stream->pos - _stream->skip);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen switch (ret) {
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen case -2:
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen i_assert(_stream->skip != _stream->pos);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen break;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen case -1:
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (stream->stream_errno != 0) {
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen /* error handling should be easier if we now just
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen assume the stream is now at EOF */
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen stream->eof = TRUE;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen errno = stream->stream_errno;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen } else {
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen i_assert(stream->eof);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen i_assert(old_size == _stream->pos - _stream->skip);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen }
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen break;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen case 0:
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen i_assert(!stream->blocking);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen break;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen default:
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen i_assert(ret > 0);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen i_assert(_stream->skip < _stream->pos);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen i_assert((size_t)ret+old_size == _stream->pos - _stream->skip);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen _stream->last_read_timeval = ioloop_timeval;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen break;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen }
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (stream->stream_errno != 0) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen /* error handling should be easier if we now just
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen assume the stream is now at EOF. Note that we could get here
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen even if read() didn't return -1, although that's a little
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen bit sloppy istream implementation. */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen stream->eof = TRUE;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen }
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen i_stream_update(_stream);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen /* verify that parents' access_counters are valid. the parent's
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen i_stream_read() should guarantee this. */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen i_assert(!i_stream_is_buffer_invalid(_stream));
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return ret;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen}
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenint i_stream_read_more_memarea(struct istream *stream,
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen const unsigned char **data_r, size_t *size_r)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen{
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen *data_r = i_stream_get_data(stream, size_r);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (*size_r > 0)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return 1;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen int ret = i_stream_read_memarea(stream);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen *data_r = i_stream_get_data(stream, size_r);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return ret;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen}
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenvoid i_stream_get_last_read_time(struct istream *stream, struct timeval *tv_r)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen{
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen *tv_r = stream->real_stream->last_read_timeval;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen}
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenssize_t i_stream_read_copy_from_parent(struct istream *istream)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen{
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen struct istream_private *stream = istream->real_stream;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen size_t pos;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen ssize_t ret;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen stream->pos -= stream->skip;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen stream->skip = 0;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen stream->buffer = i_stream_get_data(stream->parent, &pos);
42270b2d8d9bb0d04b16e0ead727154b32399a3fTimo Sirainen if (pos > stream->pos)
42270b2d8d9bb0d04b16e0ead727154b32399a3fTimo Sirainen ret = 0;
42270b2d8d9bb0d04b16e0ead727154b32399a3fTimo Sirainen else do {
42270b2d8d9bb0d04b16e0ead727154b32399a3fTimo Sirainen if ((ret = i_stream_read_memarea(stream->parent)) == -2) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen i_stream_update(stream);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return -2;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen }
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen stream->istream.stream_errno = stream->parent->stream_errno;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen stream->istream.eof = stream->parent->eof;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen stream->buffer = i_stream_get_data(stream->parent, &pos);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen /* check again, in case the parent stream had been seeked
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen backwards and the previous read() didn't get us far
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen enough. */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen } while (pos <= stream->pos && ret > 0);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen ret = pos > stream->pos ? (ssize_t)(pos - stream->pos) :
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen (ret == 0 ? 0 : -1);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen stream->pos = pos;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen i_assert(ret != -1 || stream->istream.eof ||
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen stream->istream.stream_errno != 0);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen i_stream_update(stream);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return ret;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen}
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenvoid i_stream_free_buffer(struct istream_private *stream)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen{
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (stream->memarea != NULL) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen memarea_unref(&stream->memarea);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen stream->w_buffer = NULL;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen } else if (stream->w_buffer != NULL) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen i_free_and_null(stream->w_buffer);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen } else {
4182d8cd818e76856a5a1e25b343fe5ddf69fd8eTimo Sirainen /* don't know how to free it */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen }
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen stream->buffer_size = 0;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen}
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenvoid i_stream_skip(struct istream *stream, uoff_t count)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen{
4182d8cd818e76856a5a1e25b343fe5ddf69fd8eTimo Sirainen struct istream_private *_stream = stream->real_stream;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen size_t data_size;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen data_size = _stream->pos - _stream->skip;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (count <= data_size) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen /* within buffer */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen stream->v_offset += count;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen _stream->skip += count;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (_stream->nonpersistent_buffers &&
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen _stream->skip == _stream->pos) {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen _stream->skip = _stream->pos = 0;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen i_stream_free_buffer(_stream);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen }
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen return;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen }
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen /* have to seek forward */
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen count -= data_size;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen _stream->skip = _stream->pos;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen stream->v_offset += data_size;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (unlikely(stream->closed || stream->stream_errno != 0))
d22301419109ed4a38351715e6760011421dadecTimo Sirainen return;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen _stream->seek(_stream, stream->v_offset + count, FALSE);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen}
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenstatic bool i_stream_can_optimize_seek(struct istream_private *stream)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen{
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (stream->parent == NULL)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return TRUE;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen /* use the fast route only if the parent stream hasn't been changed */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (stream->access_counter !=
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen stream->parent->real_stream->access_counter)
d22301419109ed4a38351715e6760011421dadecTimo Sirainen return FALSE;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return i_stream_can_optimize_seek(stream->parent->real_stream);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen}
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainenvoid i_stream_seek(struct istream *stream, uoff_t v_offset)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen{
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen struct istream_private *_stream = stream->real_stream;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (v_offset >= stream->v_offset &&
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen i_stream_can_optimize_seek(_stream))
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen i_stream_skip(stream, v_offset - stream->v_offset);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen else {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (unlikely(stream->closed || stream->stream_errno != 0)) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen stream->eof = TRUE;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen return;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen }
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen stream->eof = FALSE;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen _stream->seek(_stream, v_offset, FALSE);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen }
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen i_stream_update(_stream);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen}
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenvoid i_stream_seek_mark(struct istream *stream, uoff_t v_offset)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen{
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen struct istream_private *_stream = stream->real_stream;
eef4ba0cc3e78f8c26804c1c9251a76580a41f0cTimo Sirainen
eef4ba0cc3e78f8c26804c1c9251a76580a41f0cTimo Sirainen if (unlikely(stream->closed || stream->stream_errno != 0))
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen stream->eof = FALSE;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen _stream->seek(_stream, v_offset, TRUE);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen i_stream_update(_stream);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen}
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainenvoid i_stream_sync(struct istream *stream)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen{
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen struct istream_private *_stream = stream->real_stream;
eef4ba0cc3e78f8c26804c1c9251a76580a41f0cTimo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (unlikely(stream->closed || stream->stream_errno != 0))
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen return;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (_stream->sync != NULL) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen _stream->sync(_stream);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen i_stream_update(_stream);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen }
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen}
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainenint i_stream_stat(struct istream *stream, bool exact, const struct stat **st_r)
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen{
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen struct istream_private *_stream = stream->real_stream;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (unlikely(stream->closed || stream->stream_errno != 0))
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen return -1;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (_stream->stat(_stream, exact) < 0) {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen stream->eof = TRUE;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen return -1;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen }
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen *st_r = &_stream->statbuf;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen return 0;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen}
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
e3736b5d480878031c386ac55d201fcf08e68766Timo Sirainenint i_stream_get_size(struct istream *stream, bool exact, uoff_t *size_r)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen{
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen struct istream_private *_stream = stream->real_stream;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (unlikely(stream->closed || stream->stream_errno != 0))
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen return -1;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen int ret;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if ((ret = _stream->get_size(_stream, exact, size_r)) < 0)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen stream->eof = TRUE;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen return ret;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen}
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainenbool i_stream_have_bytes_left(struct istream *stream)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen{
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen return i_stream_get_data_size(stream) > 0 || !stream->eof;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen}
e3736b5d480878031c386ac55d201fcf08e68766Timo Sirainen
e3736b5d480878031c386ac55d201fcf08e68766Timo Sirainenbool i_stream_read_eof(struct istream *stream)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen{
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (i_stream_get_data_size(stream) == 0)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen (void)i_stream_read(stream);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen return !i_stream_have_bytes_left(stream);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen}
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainenuoff_t i_stream_get_absolute_offset(struct istream *stream)
e3736b5d480878031c386ac55d201fcf08e68766Timo Sirainen{
e3736b5d480878031c386ac55d201fcf08e68766Timo Sirainen uoff_t abs_offset = stream->v_offset;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen while (stream != NULL) {
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen abs_offset += stream->real_stream->start_offset;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen stream = stream->real_stream->parent;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen }
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen return abs_offset;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen}
fb7dd075cf883e5e7defbc0c8fb8326e30bdccdeTimo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainenstatic char *i_stream_next_line_finish(struct istream_private *stream, size_t i)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen{
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen char *ret;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen size_t end;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
a21823d90cee6a18aeab0378637472c7e3fbbab2Timo Sirainen if (i > 0 && stream->buffer[i-1] == '\r') {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen end = i - 1;
a21823d90cee6a18aeab0378637472c7e3fbbab2Timo Sirainen stream->line_crlf = TRUE;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen } else {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen end = i;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen stream->line_crlf = FALSE;
a21823d90cee6a18aeab0378637472c7e3fbbab2Timo Sirainen }
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
a21823d90cee6a18aeab0378637472c7e3fbbab2Timo Sirainen if (stream->buffer == stream->w_buffer) {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen /* modify the buffer directly */
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen stream->w_buffer[end] = '\0';
a21823d90cee6a18aeab0378637472c7e3fbbab2Timo Sirainen ret = (char *)stream->w_buffer + stream->skip;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen } else {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen /* use a temporary string to return it */
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (stream->line_str == NULL)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen stream->line_str = str_new(default_pool, 256);
a21823d90cee6a18aeab0378637472c7e3fbbab2Timo Sirainen str_truncate(stream->line_str, 0);
a21823d90cee6a18aeab0378637472c7e3fbbab2Timo Sirainen str_append_n(stream->line_str, stream->buffer + stream->skip,
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen end - stream->skip);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen ret = str_c_modifiable(stream->line_str);
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen }
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen if (i < stream->pos)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen i++;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen stream->istream.v_offset += i - stream->skip;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen stream->skip = i;
a21823d90cee6a18aeab0378637472c7e3fbbab2Timo Sirainen return ret;
a21823d90cee6a18aeab0378637472c7e3fbbab2Timo Sirainen}
a21823d90cee6a18aeab0378637472c7e3fbbab2Timo Sirainen
a21823d90cee6a18aeab0378637472c7e3fbbab2Timo Sirainenstatic char *i_stream_last_line(struct istream_private *_stream)
a21823d90cee6a18aeab0378637472c7e3fbbab2Timo Sirainen{
a21823d90cee6a18aeab0378637472c7e3fbbab2Timo Sirainen if (_stream->istream.eof && _stream->skip != _stream->pos &&
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen _stream->return_nolf_line) {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen /* the last line is missing LF and we want to return it. */
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen return i_stream_next_line_finish(_stream, _stream->pos);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen }
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen return NULL;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen}
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
a21823d90cee6a18aeab0378637472c7e3fbbab2Timo Sirainenchar *i_stream_next_line(struct istream *stream)
41955c400476941fa274f18b106a5922866fd780Timo Sirainen{
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen struct istream_private *_stream = stream->real_stream;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen const unsigned char *pos;
a21823d90cee6a18aeab0378637472c7e3fbbab2Timo Sirainen
e3736b5d480878031c386ac55d201fcf08e68766Timo Sirainen if (_stream->skip >= _stream->pos)
e3736b5d480878031c386ac55d201fcf08e68766Timo Sirainen return NULL;
a21823d90cee6a18aeab0378637472c7e3fbbab2Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen pos = memchr(_stream->buffer + _stream->skip, '\n',
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen _stream->pos - _stream->skip);
d516e6848ecfbc7381abe9414fd8011fdf9d8c95Timo Sirainen if (pos != NULL) {
a21823d90cee6a18aeab0378637472c7e3fbbab2Timo Sirainen return i_stream_next_line_finish(_stream,
d516e6848ecfbc7381abe9414fd8011fdf9d8c95Timo Sirainen pos - _stream->buffer);
d516e6848ecfbc7381abe9414fd8011fdf9d8c95Timo Sirainen } else {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen return i_stream_last_line(_stream);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen }
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen}
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
c9dea5c23355dea35c6fa423de69f6507852efe4Timo Sirainenchar *i_stream_read_next_line(struct istream *stream)
c9dea5c23355dea35c6fa423de69f6507852efe4Timo Sirainen{
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen char *line;
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen for (;;) {
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen line = i_stream_next_line(stream);
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen if (line != NULL)
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen break;
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen switch (i_stream_read(stream)) {
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen case -2:
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen io_stream_set_error(&stream->real_stream->iostream,
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen "Line is too long (over %"PRIuSIZE_T
c9dea5c23355dea35c6fa423de69f6507852efe4Timo Sirainen " bytes at offset %"PRIuUOFF_T")",
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen i_stream_get_data_size(stream), stream->v_offset);
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen stream->stream_errno = errno = ENOBUFS;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen stream->eof = TRUE;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen return NULL;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen case -1:
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen return i_stream_last_line(stream->real_stream);
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen case 0:
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen return NULL;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen }
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen }
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen return line;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen}
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainenbool i_stream_last_line_crlf(struct istream *stream)
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen{
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen return stream->real_stream->line_crlf;
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen}
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainenstatic bool i_stream_is_buffer_invalid(const struct istream_private *stream)
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen{
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen if (stream->parent == NULL) {
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen /* the buffer can't point to parent, because it doesn't exist */
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen return FALSE;
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen }
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen if (stream->w_buffer != NULL) {
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen /* we can pretty safely assume that the stream is using its
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen own private buffer, so it can never become invalid. */
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen return FALSE;
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen }
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen if (stream->access_counter !=
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen stream->parent->real_stream->access_counter) {
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen /* parent has been modified behind this stream, we can't trust
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen that our buffer is valid */
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen return TRUE;
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen }
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen return i_stream_is_buffer_invalid(stream->parent->real_stream);
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen}
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainenconst unsigned char *
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Siraineni_stream_get_data(struct istream *stream, size_t *size_r)
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen{
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen struct istream_private *_stream = stream->real_stream;
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen if (_stream->skip >= _stream->pos) {
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen *size_r = 0;
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen return uchar_empty_ptr;
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen }
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen if (i_stream_is_buffer_invalid(_stream)) {
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen /* This stream may be using parent's buffer directly as
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen _stream->buffer, but the parent stream has already been
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen modified indirectly. This means that the buffer might no
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen longer point to where we assume it points to. So we'll
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen just return the stream as empty until it's read again.
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen It's a bit ugly to suddenly drop data from the stream that
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen was already read, but since this happens only with shared
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen parent istreams the caller is hopefully aware enough that
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen something like this might happen. The other solutions would
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen be to a) try to automatically read the data back (but we
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen can't handle errors..) or b) always copy data to stream's
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen own buffer instead of pointing to parent's buffer (but this
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen causes data copying that is nearly always unnecessary). */
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen *size_r = 0;
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen /* if we had already read until EOF, mark the stream again as
6cd263d9a9812174a63e852ad6a9a8cdf63cfd8eTimo Sirainen not being at the end of file. */
3b1dd975d0c543d76679593f86e136d43bf40635Timo Sirainen if (stream->stream_errno == 0) {
6cd263d9a9812174a63e852ad6a9a8cdf63cfd8eTimo Sirainen _stream->skip = _stream->pos = 0;
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen stream->eof = FALSE;
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen }
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen return uchar_empty_ptr;
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen }
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen *size_r = _stream->pos - _stream->skip;
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen return _stream->buffer + _stream->skip;
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen}
6cd263d9a9812174a63e852ad6a9a8cdf63cfd8eTimo Sirainen
6cd263d9a9812174a63e852ad6a9a8cdf63cfd8eTimo Sirainensize_t i_stream_get_data_size(struct istream *stream)
6cd263d9a9812174a63e852ad6a9a8cdf63cfd8eTimo Sirainen{
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen size_t size;
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen (void)i_stream_get_data(stream, &size);
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen return size;
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen}
3b1dd975d0c543d76679593f86e136d43bf40635Timo Sirainen
6cd263d9a9812174a63e852ad6a9a8cdf63cfd8eTimo Sirainenunsigned char *i_stream_get_modifiable_data(struct istream *stream,
3b1dd975d0c543d76679593f86e136d43bf40635Timo Sirainen size_t *size_r)
3b1dd975d0c543d76679593f86e136d43bf40635Timo Sirainen{
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen struct istream_private *_stream = stream->real_stream;
3b1dd975d0c543d76679593f86e136d43bf40635Timo Sirainen
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen if (_stream->skip >= _stream->pos || _stream->w_buffer == NULL) {
3b1dd975d0c543d76679593f86e136d43bf40635Timo Sirainen *size_r = 0;
3b1dd975d0c543d76679593f86e136d43bf40635Timo Sirainen return NULL;
6cd263d9a9812174a63e852ad6a9a8cdf63cfd8eTimo Sirainen }
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen *size_r = _stream->pos - _stream->skip;
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen return _stream->w_buffer + _stream->skip;
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen}
6cd263d9a9812174a63e852ad6a9a8cdf63cfd8eTimo Sirainen
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainenint i_stream_read_data(struct istream *stream, const unsigned char **data_r,
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen size_t *size_r, size_t threshold)
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen{
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen ssize_t ret = 0;
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen bool read_more = FALSE;
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen do {
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen *data_r = i_stream_get_data(stream, size_r);
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen if (*size_r > threshold)
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen return 1;
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen /* we need more data */
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen ret = i_stream_read(stream);
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen if (ret > 0)
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen read_more = TRUE;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen } while (ret > 0);
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen *data_r = i_stream_get_data(stream, size_r);
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen if (ret == -2)
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen return -2;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen if (ret == 0) {
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen /* need to read more */
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen i_assert(!stream->blocking);
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen return 0;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen }
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen if (stream->eof) {
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen if (read_more) {
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen /* we read at least some new data */
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen return 0;
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen }
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen } else {
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen i_assert(stream->stream_errno != 0);
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen }
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen return -1;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen}
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainenvoid i_stream_compress(struct istream_private *stream)
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen{
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen i_assert(stream->memarea == NULL ||
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen memarea_get_refcount(stream->memarea) == 1);
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen if (stream->skip != stream->pos) {
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen memmove(stream->w_buffer, stream->w_buffer + stream->skip,
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen stream->pos - stream->skip);
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen }
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen stream->pos -= stream->skip;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen stream->skip = 0;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen}
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen
7fc0f80480063a9d4cb9e8c07b50db2a5627799eTimo Sirainenstatic void i_stream_w_buffer_free(void *buf)
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen{
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen i_free(buf);
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen}
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainenstatic void
905457e0982fc15930d90e174f271dc69f9afcf9Timo Siraineni_stream_w_buffer_realloc(struct istream_private *stream, size_t old_size)
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen{
c20d64512d687f0abf7c1a0aa4fa0174da0a18e3Timo Sirainen void *new_buffer;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen if (stream->memarea != NULL &&
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen memarea_get_refcount(stream->memarea) == 1) {
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen /* Nobody else is referencing the memarea.
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen We can just reallocate it. */
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen memarea_free_without_callback(&stream->memarea);
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen new_buffer = i_realloc(stream->w_buffer, old_size,
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen stream->buffer_size);
c20d64512d687f0abf7c1a0aa4fa0174da0a18e3Timo Sirainen } else {
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen new_buffer = i_malloc(stream->buffer_size);
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen if (old_size > 0) {
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen i_assert(stream->w_buffer != NULL);
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen memcpy(new_buffer, stream->w_buffer, old_size);
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen }
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen if (stream->memarea != NULL)
c20d64512d687f0abf7c1a0aa4fa0174da0a18e3Timo Sirainen memarea_unref(&stream->memarea);
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen }
c20d64512d687f0abf7c1a0aa4fa0174da0a18e3Timo Sirainen
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen stream->w_buffer = new_buffer;
c20d64512d687f0abf7c1a0aa4fa0174da0a18e3Timo Sirainen stream->buffer = new_buffer;
c20d64512d687f0abf7c1a0aa4fa0174da0a18e3Timo Sirainen
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen stream->memarea = memarea_init(stream->w_buffer, stream->buffer_size,
c20d64512d687f0abf7c1a0aa4fa0174da0a18e3Timo Sirainen i_stream_w_buffer_free, new_buffer);
c20d64512d687f0abf7c1a0aa4fa0174da0a18e3Timo Sirainen}
c20d64512d687f0abf7c1a0aa4fa0174da0a18e3Timo Sirainen
c20d64512d687f0abf7c1a0aa4fa0174da0a18e3Timo Sirainenvoid i_stream_grow_buffer(struct istream_private *stream, size_t bytes)
c20d64512d687f0abf7c1a0aa4fa0174da0a18e3Timo Sirainen{
280b771b7ec7e49caa399540dfe8faf42999a1adTimo Sirainen size_t old_size, max_size;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen old_size = stream->buffer_size;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen stream->buffer_size = stream->pos + bytes;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (stream->buffer_size <= stream->init_buffer_size)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen stream->buffer_size = stream->init_buffer_size;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen else
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen stream->buffer_size = nearest_power(stream->buffer_size);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen max_size = i_stream_get_max_buffer_size(&stream->istream);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen i_assert(max_size > 0);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (stream->buffer_size > max_size)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen stream->buffer_size = max_size;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (stream->buffer_size <= old_size)
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen stream->buffer_size = old_size;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen else
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen i_stream_w_buffer_realloc(stream, old_size);
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen}
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainenbool i_stream_try_alloc(struct istream_private *stream,
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen size_t wanted_size, size_t *size_r)
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen{
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen i_assert(wanted_size > 0);
7fc0f80480063a9d4cb9e8c07b50db2a5627799eTimo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (wanted_size > stream->buffer_size - stream->pos) {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (stream->skip > 0) {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen /* remove the unused bytes from beginning of buffer */
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (stream->memarea != NULL &&
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen memarea_get_refcount(stream->memarea) > 1) {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen /* The memarea is still referenced. We can't
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen overwrite data until extra references are
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen gone. */
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen i_stream_w_buffer_realloc(stream, stream->buffer_size);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen }
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen i_stream_compress(stream);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen } else if (stream->buffer_size < i_stream_get_max_buffer_size(&stream->istream)) {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen /* buffer is full - grow it */
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen i_stream_grow_buffer(stream, I_STREAM_MIN_SIZE);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen }
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen }
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen *size_r = stream->buffer_size - stream->pos;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (stream->try_alloc_limit > 0 &&
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen *size_r > stream->try_alloc_limit)
41955c400476941fa274f18b106a5922866fd780Timo Sirainen *size_r = stream->try_alloc_limit;
41955c400476941fa274f18b106a5922866fd780Timo Sirainen return *size_r > 0;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen}
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainenbool ATTR_NOWARN_UNUSED_RESULT
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Siraineni_stream_try_alloc_avoid_compress(struct istream_private *stream,
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen size_t wanted_size, size_t *size_r)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen{
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen size_t old_skip = stream->skip;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen /* try first with skip=0, so no compression is done */
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen stream->skip = 0;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen bool ret = i_stream_try_alloc(stream, wanted_size, size_r);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen stream->skip = old_skip;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (ret || old_skip == 0)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen return ret;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen /* it's full. try with compression. */
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen return i_stream_try_alloc(stream, wanted_size, size_r);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen}
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainenvoid *i_stream_alloc(struct istream_private *stream, size_t size)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen{
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen size_t old_size, avail_size;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen i_stream_try_alloc(stream, size, &avail_size);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (avail_size < size) {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen old_size = stream->buffer_size;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen stream->buffer_size = nearest_power(stream->pos + size);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen i_stream_w_buffer_realloc(stream, old_size);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen i_stream_try_alloc(stream, size, &avail_size);
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen i_assert(avail_size >= size);
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen }
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen return stream->w_buffer + stream->pos;
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen}
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainenbool i_stream_add_data(struct istream *_stream, const unsigned char *data,
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen size_t size)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen{
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen struct istream_private *stream = _stream->real_stream;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen size_t size2;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen i_stream_try_alloc(stream, size, &size2);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (size > size2)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen return FALSE;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen memcpy(stream->w_buffer + stream->pos, data, size);
41955c400476941fa274f18b106a5922866fd780Timo Sirainen stream->pos += size;
41955c400476941fa274f18b106a5922866fd780Timo Sirainen return TRUE;
41955c400476941fa274f18b106a5922866fd780Timo Sirainen}
41955c400476941fa274f18b106a5922866fd780Timo Sirainen
41955c400476941fa274f18b106a5922866fd780Timo Sirainenstruct istream *i_stream_get_root_io(struct istream *stream)
41955c400476941fa274f18b106a5922866fd780Timo Sirainen{
41955c400476941fa274f18b106a5922866fd780Timo Sirainen while (stream->real_stream->parent != NULL) {
41955c400476941fa274f18b106a5922866fd780Timo Sirainen i_assert(stream->real_stream->io == NULL);
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen stream = stream->real_stream->parent;
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen }
41955c400476941fa274f18b106a5922866fd780Timo Sirainen return stream;
41955c400476941fa274f18b106a5922866fd780Timo Sirainen}
41955c400476941fa274f18b106a5922866fd780Timo Sirainen
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainenvoid i_stream_set_input_pending(struct istream *stream, bool pending)
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen{
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen if (!pending)
41955c400476941fa274f18b106a5922866fd780Timo Sirainen return;
41955c400476941fa274f18b106a5922866fd780Timo Sirainen
41955c400476941fa274f18b106a5922866fd780Timo Sirainen stream = i_stream_get_root_io(stream);
41955c400476941fa274f18b106a5922866fd780Timo Sirainen if (stream->real_stream->io != NULL)
41955c400476941fa274f18b106a5922866fd780Timo Sirainen io_set_pending(stream->real_stream->io);
41955c400476941fa274f18b106a5922866fd780Timo Sirainen}
41955c400476941fa274f18b106a5922866fd780Timo Sirainen
41955c400476941fa274f18b106a5922866fd780Timo Sirainenvoid i_stream_switch_ioloop_to(struct istream *stream, struct ioloop *ioloop)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen{
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen io_stream_switch_ioloop_to(&stream->real_stream->iostream, ioloop);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen do {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (stream->real_stream->switch_ioloop_to != NULL) {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen stream->real_stream->switch_ioloop_to(
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen stream->real_stream, ioloop);
2584e86cc2d8c31ba30a4109cf4ba09d1e37e28aTimo Sirainen }
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen stream = stream->real_stream->parent;
41955c400476941fa274f18b106a5922866fd780Timo Sirainen } while (stream != NULL);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen}
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainenvoid i_stream_switch_ioloop(struct istream *stream)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen{
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen i_stream_switch_ioloop_to(stream, current_ioloop);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen}
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainenvoid i_stream_set_io(struct istream *stream, struct io *io)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen{
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen stream = i_stream_get_root_io(stream);
41955c400476941fa274f18b106a5922866fd780Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen i_assert(stream->real_stream->io == NULL);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen stream->real_stream->io = io;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen}
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainenvoid i_stream_unset_io(struct istream *stream, struct io *io)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen{
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen stream = i_stream_get_root_io(stream);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen i_assert(stream->real_stream->io == io);
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen stream->real_stream->io = NULL;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen}
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainenstatic void
905457e0982fc15930d90e174f271dc69f9afcf9Timo Siraineni_stream_default_set_max_buffer_size(struct iostream_private *stream,
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen size_t max_size)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen{
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen struct istream_private *_stream = (struct istream_private *)stream;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen _stream->max_buffer_size = max_size;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (_stream->parent != NULL)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen i_stream_set_max_buffer_size(_stream->parent, max_size);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen}
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
2584e86cc2d8c31ba30a4109cf4ba09d1e37e28aTimo Sirainenstatic void i_stream_default_close(struct iostream_private *stream,
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen bool close_parent)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen{
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen struct istream_private *_stream = (struct istream_private *)stream;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (close_parent)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen i_stream_close(_stream->parent);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen}
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainenstatic void i_stream_default_destroy(struct iostream_private *stream)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen{
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen struct istream_private *_stream = (struct istream_private *)stream;
6d6c1517ef20e340a3aace406724fc8916f2d13fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen i_stream_free_buffer(_stream);
51327f2489a4e0e615eb9f7d921473cf8512bb79Timo Sirainen i_stream_unref(&_stream->parent);
51327f2489a4e0e615eb9f7d921473cf8512bb79Timo Sirainen}
6d6c1517ef20e340a3aace406724fc8916f2d13fTimo Sirainen
6d6c1517ef20e340a3aace406724fc8916f2d13fTimo Sirainenstatic void
6d6c1517ef20e340a3aace406724fc8916f2d13fTimo Siraineni_stream_default_seek_seekable(struct istream_private *stream,
6d6c1517ef20e340a3aace406724fc8916f2d13fTimo Sirainen uoff_t v_offset, bool mark ATTR_UNUSED)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen{
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen stream->istream.v_offset = v_offset;
6d6c1517ef20e340a3aace406724fc8916f2d13fTimo Sirainen stream->skip = stream->pos = 0;
6d6c1517ef20e340a3aace406724fc8916f2d13fTimo Sirainen}
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainenvoid i_stream_default_seek_nonseekable(struct istream_private *stream,
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen uoff_t v_offset, bool mark ATTR_UNUSED)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen{
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen size_t available;
6d6c1517ef20e340a3aace406724fc8916f2d13fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (stream->istream.v_offset > v_offset)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen i_panic("stream %s doesn't support seeking backwards",
5b486fdbf2077a994337dc8bd4477ec51d5daf4eTimo Sirainen i_stream_get_name(&stream->istream));
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen while (stream->istream.v_offset < v_offset) {
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen (void)i_stream_read(&stream->istream);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen available = stream->pos - stream->skip;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (available == 0) {
6d6c1517ef20e340a3aace406724fc8916f2d13fTimo Sirainen if (stream->istream.stream_errno != 0) {
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen /* read failed */
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen return;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen }
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen io_stream_set_error(&stream->iostream,
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen "Can't seek to offset %"PRIuUOFF_T
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen ", because we have data only up to offset %"
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen PRIuUOFF_T" (eof=%d)", v_offset,
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen stream->istream.v_offset, stream->istream.eof ? 1 : 0);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen stream->istream.stream_errno = ESPIPE;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen return;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen }
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (available <= v_offset - stream->istream.v_offset)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen i_stream_skip(&stream->istream, available);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen else {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen i_stream_skip(&stream->istream,
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen v_offset - stream->istream.v_offset);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen }
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen }
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen}
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainenstatic int
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Siraineni_stream_default_stat(struct istream_private *stream, bool exact)
3c097377e865689723c8737537886b01a5ebd3d9Timo Sirainen{
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen const struct stat *st;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (stream->parent == NULL)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen return stream->istream.stream_errno == 0 ? 0 : -1;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen if (i_stream_stat(stream->parent, exact, &st) < 0) {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen stream->istream.stream_errno = stream->parent->stream_errno;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen return -1;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen }
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen stream->statbuf = *st;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (exact && !stream->stream_size_passthrough) {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen /* exact size is not known, even if parent returned something */
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen stream->statbuf.st_size = -1;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen }
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen return 0;
2584e86cc2d8c31ba30a4109cf4ba09d1e37e28aTimo Sirainen}
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainenstatic int
51327f2489a4e0e615eb9f7d921473cf8512bb79Timo Siraineni_stream_default_get_size(struct istream_private *stream,
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen bool exact, uoff_t *size_r)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen{
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (stream->stat(stream, exact) < 0)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen return -1;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (stream->statbuf.st_size == -1)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen return 0;
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen *size_r = stream->statbuf.st_size;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen return 1;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen}
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainenvoid i_stream_init_parent(struct istream_private *_stream,
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen struct istream *parent)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen{
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen _stream->access_counter = parent->real_stream->access_counter;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen _stream->parent = parent;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen _stream->parent_start_offset = parent->v_offset;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen _stream->parent_expected_offset = parent->v_offset;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen _stream->start_offset = parent->v_offset;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen /* if parent stream is an istream-error, copy the error */
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen _stream->istream.stream_errno = parent->stream_errno;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen _stream->istream.eof = parent->eof;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen i_stream_ref(parent);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen}
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainenstruct istream *
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Siraineni_stream_create(struct istream_private *_stream, struct istream *parent, int fd,
ddd5fb9499ae08f7f0d4b41306bb4fca053e493bTimo Sirainen enum istream_create_flag flags)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen{
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen bool noop_snapshot = (flags & ISTREAM_CREATE_FLAG_NOOP_SNAPSHOT) != 0;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen _stream->fd = fd;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (parent != NULL)
ddd5fb9499ae08f7f0d4b41306bb4fca053e493bTimo Sirainen i_stream_init_parent(_stream, parent);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen else if (_stream->memarea == NULL && !noop_snapshot) {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen /* The stream has no parent and no memarea yet. We'll assume
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen that it wants to be using memareas for the reads. */
ddd5fb9499ae08f7f0d4b41306bb4fca053e493bTimo Sirainen _stream->memarea = memarea_init_empty();
ddd5fb9499ae08f7f0d4b41306bb4fca053e493bTimo Sirainen }
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen _stream->istream.real_stream = _stream;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (_stream->iostream.close == NULL)
ddd5fb9499ae08f7f0d4b41306bb4fca053e493bTimo Sirainen _stream->iostream.close = i_stream_default_close;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (_stream->iostream.destroy == NULL)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen _stream->iostream.destroy = i_stream_default_destroy;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (_stream->seek == NULL) {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen _stream->seek = _stream->istream.seekable ?
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen i_stream_default_seek_seekable :
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen i_stream_default_seek_nonseekable;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen }
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (_stream->stat == NULL)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen _stream->stat = i_stream_default_stat;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (_stream->get_size == NULL)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen _stream->get_size = i_stream_default_get_size;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (_stream->snapshot == NULL) {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen _stream->snapshot = noop_snapshot ?
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen i_stream_noop_snapshot :
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen i_stream_default_snapshot;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen }
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (_stream->iostream.set_max_buffer_size == NULL) {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen _stream->iostream.set_max_buffer_size =
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen i_stream_default_set_max_buffer_size;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen }
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (_stream->init_buffer_size == 0)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen _stream->init_buffer_size = I_STREAM_MIN_SIZE;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen i_zero(&_stream->statbuf);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen _stream->statbuf.st_size = -1;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen _stream->statbuf.st_atime =
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen _stream->statbuf.st_mtime =
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen _stream->statbuf.st_ctime = ioloop_time;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen io_stream_init(&_stream->iostream);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (_stream->istream.stream_errno != 0)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen _stream->istream.eof = TRUE;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen return &_stream->istream;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen}
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainenstruct istream *i_stream_create_error(int stream_errno)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen{
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen struct istream_private *stream;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen stream = i_new(struct istream_private, 1);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen stream->istream.closed = TRUE;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen stream->istream.readable_fd = FALSE;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen stream->istream.blocking = TRUE;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen stream->istream.seekable = TRUE;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen stream->istream.eof = TRUE;
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen stream->istream.stream_errno = stream_errno;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen i_stream_create(stream, NULL, -1, 0);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen i_stream_set_name(&stream->istream, "(error)");
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen return &stream->istream;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen}
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainenstruct istream *
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Siraineni_stream_create_error_str(int stream_errno, const char *fmt, ...)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen{
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen struct istream *input;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen va_list args;
2b9fd042e701cfe7d79c4294a5ab401d6ec9ce18Timo Sirainen
2b9fd042e701cfe7d79c4294a5ab401d6ec9ce18Timo Sirainen va_start(args, fmt);
2b9fd042e701cfe7d79c4294a5ab401d6ec9ce18Timo Sirainen input = i_stream_create_error(stream_errno);
2b9fd042e701cfe7d79c4294a5ab401d6ec9ce18Timo Sirainen io_stream_set_verror(&input->real_stream->iostream, fmt, args);
2b9fd042e701cfe7d79c4294a5ab401d6ec9ce18Timo Sirainen va_end(args);
ddd5fb9499ae08f7f0d4b41306bb4fca053e493bTimo Sirainen return input;
ddd5fb9499ae08f7f0d4b41306bb4fca053e493bTimo Sirainen}
ddd5fb9499ae08f7f0d4b41306bb4fca053e493bTimo Sirainen