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; }
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; }
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); }
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); } }
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); }
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; }