static enum ostream_send_istream_result o_stream_temp_send_istream(struct ostream_private *_outstream, struct istream *instream) { struct temp_ostream *outstream = (struct temp_ostream *)_outstream; enum ostream_send_istream_result res; if ((outstream->flags & IOSTREAM_TEMP_FLAG_TRY_FD_DUP) != 0) { if (o_stream_temp_dup_istream(outstream, instream, &res)) return res; outstream->flags &= ~IOSTREAM_TEMP_FLAG_TRY_FD_DUP; } return io_stream_copy(&outstream->ostream.ostream, instream); }
static off_t o_stream_temp_send_istream(struct ostream_private *_outstream, struct istream *instream) { struct temp_ostream *outstream = (struct temp_ostream *)_outstream; uoff_t orig_offset; int ret; if ((outstream->flags & IOSTREAM_TEMP_FLAG_TRY_FD_DUP) != 0) { orig_offset = outstream->dupstream_offset; if ((ret = o_stream_temp_dup_istream(outstream, instream)) > 0) return outstream->dupstream_offset - orig_offset; if (ret < 0) return -1; outstream->flags &= ~IOSTREAM_TEMP_FLAG_TRY_FD_DUP; } return io_stream_copy(&outstream->ostream.ostream, instream); }
static int o_stream_temp_dup_cancel(struct temp_ostream *tstream) { struct istream *input; uoff_t size = tstream->dupstream_offset - tstream->dupstream_start_offset; off_t ret; i_stream_seek(tstream->dupstream, tstream->dupstream_start_offset); input = i_stream_create_limit(tstream->dupstream, size); do { ret = io_stream_copy(&tstream->ostream.ostream, input); } while (input->v_offset < tstream->dupstream_offset && ret > 0); if (ret < 0 && tstream->ostream.ostream.stream_errno == 0) { i_assert(input->stream_errno != 0); tstream->ostream.ostream.stream_errno = input->stream_errno; } i_stream_destroy(&input); i_stream_unref(&tstream->dupstream); return ret < 0 ? -1 : 0; }
static bool o_stream_temp_dup_cancel(struct temp_ostream *tstream, enum ostream_send_istream_result *res_r) { struct istream *input; uoff_t size = tstream->dupstream_offset - tstream->dupstream_start_offset; bool ret = TRUE; /* use res_r to return error */ i_stream_seek(tstream->dupstream, tstream->dupstream_start_offset); tstream->ostream.ostream.offset = 0; input = i_stream_create_limit(tstream->dupstream, size); i_stream_unref(&tstream->dupstream); *res_r = io_stream_copy(&tstream->ostream.ostream, input); switch (*res_r) { case OSTREAM_SEND_ISTREAM_RESULT_FINISHED: /* everything copied */ ret = FALSE; break; case OSTREAM_SEND_ISTREAM_RESULT_WAIT_INPUT: case OSTREAM_SEND_ISTREAM_RESULT_WAIT_OUTPUT: i_unreached(); case OSTREAM_SEND_ISTREAM_RESULT_ERROR_INPUT: tstream->ostream.ostream.stream_errno = input->stream_errno; io_stream_set_error(&tstream->ostream.iostream, "iostream-temp: read(%s) failed: %s", i_stream_get_name(input), i_stream_get_error(input)); break; case OSTREAM_SEND_ISTREAM_RESULT_ERROR_OUTPUT: break; } i_stream_destroy(&input); return ret; }