Exemplo n.º 1
0
static int o_stream_temp_dup_istream(struct temp_ostream *outstream,
				     struct istream *instream)
{
	uoff_t in_size;
	off_t ret;

	if (!instream->readable_fd || i_stream_get_fd(instream) == -1)
		return 0;

	if (i_stream_get_size(instream, TRUE, &in_size) <= 0) {
		if (outstream->dupstream != NULL)
			return o_stream_temp_dup_cancel(outstream);
		return 0;
	}

	if (outstream->dupstream == NULL) {
		outstream->dupstream = instream;
		outstream->dupstream_start_offset = instream->v_offset;
		i_stream_ref(outstream->dupstream);
	} else {
		if (outstream->dupstream != instream ||
		    outstream->dupstream_offset != instream->v_offset ||
		    outstream->dupstream_offset > in_size)
			return o_stream_temp_dup_cancel(outstream);
	}
	ret = in_size - instream->v_offset;
	i_stream_seek(instream, in_size);
	outstream->dupstream_offset = instream->v_offset;
	return ret;
}
Exemplo n.º 2
0
static ssize_t
o_stream_temp_sendv(struct ostream_private *stream,
		    const struct const_iovec *iov, unsigned int iov_count)
{
	struct temp_ostream *tstream = (struct temp_ostream *)stream;
	ssize_t ret = 0;
	unsigned int i;
	enum ostream_send_istream_result res;


	tstream->flags &= ~IOSTREAM_TEMP_FLAG_TRY_FD_DUP;
	if (tstream->dupstream != NULL) {
		if (o_stream_temp_dup_cancel(tstream, &res))
			return -1;
	}

	if (tstream->fd != -1)
		return o_stream_temp_fd_sendv(tstream, iov, iov_count);

	for (i = 0; i < iov_count; i++) {
		if (tstream->buf->used + iov[i].iov_len > tstream->max_mem_size) {
			if (o_stream_temp_move_to_fd(tstream) == 0) {
				return o_stream_temp_fd_sendv(tstream, iov+i,
							      iov_count-i);
			}
			/* failed to move to temp fd, just keep it in memory */
		}
		buffer_append(tstream->buf, iov[i].iov_base, iov[i].iov_len);
		ret += iov[i].iov_len;
		stream->ostream.offset += iov[i].iov_len;
	}
	return ret;
}
Exemplo n.º 3
0
static bool
o_stream_temp_dup_istream(struct temp_ostream *outstream,
			  struct istream *instream,
			  enum ostream_send_istream_result *res_r)
{
	uoff_t in_size;

	if (!instream->readable_fd || i_stream_get_fd(instream) == -1)
		return FALSE;

	if (i_stream_get_size(instream, TRUE, &in_size) <= 0) {
		if (outstream->dupstream != NULL)
			return o_stream_temp_dup_cancel(outstream, res_r);
		return FALSE;
	}
	i_assert(instream->v_offset <= in_size);

	if (outstream->dupstream == NULL) {
		outstream->dupstream = instream;
		outstream->dupstream_start_offset = instream->v_offset;
		i_stream_ref(outstream->dupstream);
	} else {
		if (outstream->dupstream != instream ||
		    outstream->dupstream_offset != instream->v_offset ||
		    outstream->dupstream_offset > in_size)
			return o_stream_temp_dup_cancel(outstream, res_r);
	}
	i_stream_seek(instream, in_size);
	/* we should be at EOF now. o_stream_send_istream() asserts if
	   eof isn't set. */
	instream->eof = TRUE;
	outstream->dupstream_offset = instream->v_offset;
	outstream->ostream.ostream.offset =
		outstream->dupstream_offset - outstream->dupstream_start_offset;
	*res_r = OSTREAM_SEND_ISTREAM_RESULT_FINISHED;
	return TRUE;
}