Beispiel #1
0
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);
}
Beispiel #2
0
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;
}
Beispiel #3
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;
}