static void i_stream_seekable_destroy(struct iostream_private *stream) { struct seekable_istream *sstream = (struct seekable_istream *)stream; i_stream_free_buffer(&sstream->istream); i_stream_unref(&sstream->fd_input); unref_streams(sstream); if (sstream->free_context) i_free(sstream->context); i_free(sstream->temp_path); i_free(sstream->input); }
static int i_stream_seekable_stat(struct istream_private *stream, bool exact) { struct seekable_istream *sstream = (struct seekable_istream *)stream; const struct stat *st; uoff_t old_offset; ssize_t ret; if (sstream->size != (uoff_t)-1) { /* we've already reached EOF and know the size */ stream->statbuf.st_size = sstream->size; return 0; } if (sstream->membuf != NULL) { /* we want to know the full size of the file, so read until we're finished */ old_offset = stream->istream.v_offset; do { i_stream_skip(&stream->istream, stream->pos - stream->skip); } while ((ret = i_stream_seekable_read(stream)) > 0); if (ret == 0) { i_panic("i_stream_stat() used for non-blocking " "seekable stream %s offset %"PRIuUOFF_T, i_stream_get_name(sstream->cur_input), sstream->cur_input->v_offset); } i_stream_skip(&stream->istream, stream->pos - stream->skip); i_stream_seek(&stream->istream, old_offset); unref_streams(sstream); } if (stream->istream.stream_errno != 0) return -1; if (sstream->fd_input != NULL) { /* using a file backed buffer, we can use real fstat() */ if (i_stream_stat(sstream->fd_input, exact, &st) < 0) return -1; stream->statbuf = *st; } else { /* buffer is completely in memory */ i_assert(sstream->membuf != NULL); stream->statbuf.st_size = sstream->membuf->used; } return 0; }
static ssize_t read_more(struct seekable_istream *sstream) { size_t size; ssize_t ret; if (sstream->cur_input == NULL) { sstream->istream.istream.eof = TRUE; return -1; } while ((ret = i_stream_read_memarea(sstream->cur_input)) == -1) { if (sstream->cur_input->stream_errno != 0) { io_stream_set_error(&sstream->istream.iostream, "read(%s) failed: %s", i_stream_get_name(sstream->cur_input), i_stream_get_error(sstream->cur_input)); sstream->istream.istream.eof = TRUE; sstream->istream.istream.stream_errno = sstream->cur_input->stream_errno; return -1; } /* go to next stream */ sstream->cur_input = sstream->input[sstream->cur_idx++]; if (sstream->cur_input == NULL) { /* last one, EOF */ sstream->size = sstream->istream.istream.v_offset; sstream->istream.istream.eof = TRUE; unref_streams(sstream); return -1; } /* see if stream has pending data */ size = i_stream_get_data_size(sstream->cur_input); if (size != 0) return size; } return ret; }