Esempio n. 1
0
ssize_t i_stream_read_copy_from_parent(struct istream *istream)
{
	struct istream_private *stream = istream->real_stream;
	size_t pos;
	ssize_t ret;

	stream->pos -= stream->skip;
	stream->skip = 0;

	stream->buffer = i_stream_get_data(stream->parent, &pos);
	if (pos > stream->pos)
		ret = 0;
	else do {
		if ((ret = i_stream_read(stream->parent)) == -2) {
			i_stream_update(stream);
			return -2;
		}

		stream->istream.stream_errno = stream->parent->stream_errno;
		stream->istream.eof = stream->parent->eof;
		stream->buffer = i_stream_get_data(stream->parent, &pos);
		/* check again, in case the parent stream had been seeked
		   backwards and the previous read() didn't get us far
		   enough. */
	} while (pos <= stream->pos && ret > 0);

	ret = pos > stream->pos ? (ssize_t)(pos - stream->pos) :
		(ret == 0 ? 0 : -1);
	stream->pos = pos;
	i_assert(ret != -1 || stream->istream.eof ||
		 stream->istream.stream_errno != 0);
	i_stream_update(stream);
	return ret;
}
Esempio n. 2
0
ssize_t i_stream_read(struct istream *stream)
{
	struct istream_private *_stream = stream->real_stream;
	size_t old_size;
	ssize_t ret;

	if (unlikely(stream->closed || stream->stream_errno != 0)) {
		stream->eof = TRUE;
		errno = stream->stream_errno;
		return -1;
	}

	stream->eof = FALSE;

	if (_stream->parent != NULL)
		i_stream_seek(_stream->parent, _stream->parent_expected_offset);

	old_size = _stream->pos - _stream->skip;
	ret = _stream->read(_stream);
	i_assert(old_size <= _stream->pos - _stream->skip);
	switch (ret) {
	case -2:
		i_assert(_stream->skip != _stream->pos);
		break;
	case -1:
		if (stream->stream_errno != 0) {
			/* error handling should be easier if we now just
			   assume the stream is now at EOF */
			stream->eof = TRUE;
			errno = stream->stream_errno;
		} else {
			i_assert(stream->eof);
			i_assert(old_size == _stream->pos - _stream->skip);
		}
		break;
	case 0:
		i_assert(!stream->blocking);
		break;
	default:
		i_assert(ret > 0);
		i_assert(_stream->skip < _stream->pos);
		i_assert((size_t)ret+old_size == _stream->pos - _stream->skip);
		break;
	}

	if (stream->stream_errno != 0) {
		/* error handling should be easier if we now just
		   assume the stream is now at EOF. Note that we could get here
		   even if read() didn't return -1, although that's a little
		   bit sloppy istream implementation. */
		stream->eof = TRUE;
	}

	i_stream_update(_stream);
	/* verify that parents' access_counters are valid. the parent's
	   i_stream_read() should guarantee this. */
	i_assert(!i_stream_is_buffer_invalid(_stream));
	return ret;
}
Esempio n. 3
0
void i_stream_seek_mark(struct istream *stream, uoff_t v_offset)
{
	struct istream_private *_stream = stream->real_stream;

	if (unlikely(stream->closed))
		return;

	stream->eof = FALSE;
	_stream->seek(_stream, v_offset, TRUE);
	i_stream_update(_stream);
}
Esempio n. 4
0
void i_stream_sync(struct istream *stream)
{
	struct istream_private *_stream = stream->real_stream;

	if (unlikely(stream->closed))
		return;

	if (_stream->sync != NULL) {
		_stream->sync(_stream);
		i_stream_update(_stream);
	}
}
Esempio n. 5
0
void i_stream_seek(struct istream *stream, uoff_t v_offset)
{
	struct istream_private *_stream = stream->real_stream;

	if (v_offset >= stream->v_offset &&
	    i_stream_can_optimize_seek(_stream))
		i_stream_skip(stream, v_offset - stream->v_offset);
	else {
		if (unlikely(stream->closed))
			return;

		stream->eof = FALSE;
		_stream->seek(_stream, v_offset, FALSE);
	}
	i_stream_update(_stream);
}
Esempio n. 6
0
ssize_t i_stream_read(struct istream *stream)
{
	struct istream_private *_stream = stream->real_stream;
	size_t old_size;
	ssize_t ret;

	if (unlikely(stream->closed)) {
		errno = stream->stream_errno;
		return -1;
	}

	stream->eof = FALSE;
	stream->stream_errno = 0;

	if (_stream->parent != NULL)
		i_stream_seek(_stream->parent, _stream->parent_expected_offset);

	old_size = _stream->pos - _stream->skip;
	ret = _stream->read(_stream);
	switch (ret) {
	case -2:
		i_assert(_stream->skip != _stream->pos);
		break;
	case -1:
		if (stream->stream_errno != 0) {
			/* error handling should be easier if we now just
			   assume the stream is now at EOF */
			stream->eof = TRUE;
			errno = stream->stream_errno;
		} else {
			i_assert(stream->eof);
			i_assert(old_size == _stream->pos - _stream->skip);
		}
		break;
	case 0:
		i_assert(!stream->blocking);
		break;
	default:
		i_assert(ret > 0);
		i_assert(_stream->skip < _stream->pos);
		i_assert((size_t)ret+old_size == _stream->pos - _stream->skip);
		break;
	}

	i_stream_update(_stream);
	return ret;
}