iostream-temp.c revision c076ad69e28e7d41af83ada84e12019793ffcfa2
c25356d5978632df6203437e1953bcb29e0c736fTimo Sirainen/* Copyright (c) 2013-2016 Dovecot authors, see the included COPYING file */
da2aa032ccfa8e7e4a4380ef738014549f4d2c2dTimo Sirainen#define IOSTREAM_TEMP_MAX_BUF_SIZE_DEFAULT (1024*128)
5ac0b0bf32898c63da086ae169674ecac151a31eTimo Sirainen uoff_t dupstream_offset, dupstream_start_offset;
6ef7e31619edfaa17ed044b45861d106a86191efTimo Siraineno_stream_temp_close(struct iostream_private *stream,
212a34c06ff45952c008ae9eec387ced783de6cfPhil Carmody struct temp_ostream *tstream = (struct temp_ostream *)stream;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenstatic int o_stream_temp_move_to_fd(struct temp_ostream *tstream)
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen tstream->fd = safe_mkstemp_hostpid(path, 0600, (uid_t)-1, (gid_t)-1);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen i_error("safe_mkstemp(%s) failed: %m", str_c(path));
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen if (write_full(tstream->fd, tstream->buf->data, tstream->buf->used) < 0) {
c28f6aa0b70af4811c9ace9114fe827c2f503455Timo Sirainen /* make the fd available also to o_stream_get_fd(),
1a0ece3e873e3864269ed7eaed957dc10c56d25fTimo Sirainen e.g. for unit tests */
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Siraineno_stream_temp_fd_sendv(struct temp_ostream *tstream,
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen const struct const_iovec *iov, unsigned int iov_count)
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen unsigned int i;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen for (i = 0; i < iov_count; i++) {
7662010b03ffe5f2a6ecf4b4eb220d1c65efea76Timo Sirainen if (write_full(tstream->fd, iov[i].iov_base, iov[i].iov_len) < 0) {
7662010b03ffe5f2a6ecf4b4eb220d1c65efea76Timo Sirainen tstream->ostream.ostream.stream_errno = errno;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen tstream->ostream.ostream.offset += iov[i].iov_len;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Siraineno_stream_temp_sendv(struct ostream_private *stream,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen const struct const_iovec *iov, unsigned int iov_count)
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen struct temp_ostream *tstream = (struct temp_ostream *)stream;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen unsigned int i;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen tstream->flags &= ~IOSTREAM_TEMP_FLAG_TRY_FD_DUP;
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen return o_stream_temp_fd_sendv(tstream, iov, iov_count);
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen for (i = 0; i < iov_count; i++) {
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen if (tstream->buf->used + iov[i].iov_len > tstream->max_mem_size) {
7d207b1e77a7b5e3fda640e353acfc86d261fedfTimo Sirainen /* failed to move to temp fd, just keep it in memory */
7d207b1e77a7b5e3fda640e353acfc86d261fedfTimo Sirainen buffer_append(tstream->buf, iov[i].iov_base, iov[i].iov_len);
4106a25399703eb6cbb166dcbd5bb932cb2f7ad2Timo Sirainenstatic int o_stream_temp_dup_cancel(struct temp_ostream *tstream)
89e195dfb5c4b0efd9b9f459771a4467674e5b1fTimo Sirainen i_stream_seek(tstream->dupstream, tstream->dupstream_start_offset);
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen input = i_stream_create_limit(tstream->dupstream, size);
a0b6b441fc679e562e79be0fb2819ffc24ab5b74Timo Sirainen if (io_stream_copy(&tstream->ostream.ostream, input) > 0) {
89e195dfb5c4b0efd9b9f459771a4467674e5b1fTimo Sirainen /* everything copied */
6f08b98ac63c25b747120d0c8f8e319b4e26ab0fTimo Sirainen } else if (tstream->ostream.ostream.stream_errno == 0) {
7e1f68ad71d3485f1882142837b01f7a98ca8467Timo Sirainen tstream->ostream.ostream.stream_errno = input->stream_errno;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenstatic int o_stream_temp_dup_istream(struct temp_ostream *outstream,
699fdc186f982f70d990820796eaa0f12133e27cTimo Sirainen if (!instream->readable_fd || i_stream_get_fd(instream) == -1)
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen if (i_stream_get_size(instream, TRUE, &in_size) <= 0) {
4c096615cb86a826fda377b87df22c579bfe5525Timo Sirainen outstream->dupstream_start_offset = instream->v_offset;
4c096615cb86a826fda377b87df22c579bfe5525Timo Sirainen outstream->dupstream_offset != instream->v_offset ||
int ret;
return ret;
const char *name)
const char *name,
return output;
const char *for_path;
int fd;
return input;