istream-seekable.c revision 2974dca6be5120e49279f06c8aa952e5fac56048
c25356d5978632df6203437e1953bcb29e0c736fTimo Sirainen/* Copyright (c) 2005-2017 Dovecot authors, see the included COPYING file */
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen int (*fd_callback)(const char **path_r, void *context);
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen unsigned int cur_idx;
79fcd3f95a6266cc62ceaa753e56dd4456ab7c4bTimo Sirainenstatic void i_stream_seekable_close(struct iostream_private *stream,
3ddbbe03fe74b3ee7b1dff4e08ec706d7880d052Timo Sirainen struct seekable_istream *sstream = (struct seekable_istream *)stream;
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainenstatic void unref_streams(struct seekable_istream *sstream)
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen unsigned int i;
d10a370b2614712d9cb6a1dd8625f62a071b6377Timo Sirainenstatic void i_stream_seekable_destroy(struct iostream_private *stream)
f339a8e73beea7684ea634941ea82593dea522eeTimo Sirainen struct seekable_istream *sstream = (struct seekable_istream *)stream;
0dffa25d211be541ee3c953b23566a1a990789dfTimo Siraineni_stream_seekable_set_max_buffer_size(struct iostream_private *stream,
d10a370b2614712d9cb6a1dd8625f62a071b6377Timo Sirainen struct seekable_istream *sstream = (struct seekable_istream *)stream;
d10a370b2614712d9cb6a1dd8625f62a071b6377Timo Sirainen unsigned int i;
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen i_stream_set_max_buffer_size(sstream->fd_input, max_size);
a342a31752dd71ac444259ca57ad33ea6b79a572Timo Sirainen i_stream_set_max_buffer_size(sstream->input[i], max_size);
88ea893b45d3ed8d68000921db9156c03cbe1b00Timo Sirainenstatic int copy_to_temp_file(struct seekable_istream *sstream)
8039af9679af6fb56116b353fe44f7dd4c08f031Timo Sirainen struct istream_private *stream = &sstream->istream;
d10a370b2614712d9cb6a1dd8625f62a071b6377Timo Sirainen const unsigned char *buffer;
704a96fa677763eef7ae62466e14e83a2f535427Timo Sirainen fd = sstream->fd_callback(&path, sstream->context);
5ce2084ada06ade9f44fc2914c34658e9a842dc1Timo Sirainen /* copy our currently read buffer to it */
5ce2084ada06ade9f44fc2914c34658e9a842dc1Timo Sirainen i_assert(stream->pos <= sstream->buffer_peak);
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen if (write_full(fd, stream->buffer, sstream->buffer_peak) < 0) {
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen i_error("istream-seekable: write_full(%s) failed: %m", path);
27a44fcfd8d19bffe0f267f20a2b5d3fe7600fddTimo Sirainen sstream->fd_input = i_stream_create_fd_autoclose(&fd,
27a44fcfd8d19bffe0f267f20a2b5d3fe7600fddTimo Sirainen I_MAX(stream->pos, sstream->istream.max_buffer_size));
27a44fcfd8d19bffe0f267f20a2b5d3fe7600fddTimo Sirainen i_stream_set_name(sstream->fd_input, t_strdup_printf(
2cfe9983ce7a6280636ee12beccc2e865111967bTimo Sirainen "(seekable temp-istream for: %s)", i_stream_get_name(&stream->istream)));
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen /* read back the data we just had in our buffer */
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen buffer = i_stream_get_data(sstream->fd_input, &size);
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen if ((ret = i_stream_read(sstream->fd_input)) <= 0) {
d6c5ceea8521b92d10e51a59da00c792f6140b1dTimo Sirainen i_error("istream-seekable: Couldn't read back "
d6c5ceea8521b92d10e51a59da00c792f6140b1dTimo Sirainen "in-memory input %s: %s",
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen /* Set the max buffer size only after we've already read everything
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen into memory. For example with istream-data it's possible that
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen more data exists in buffer than max_buffer_size. */
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen i_stream_set_max_buffer_size(sstream->fd_input,
d6c5ceea8521b92d10e51a59da00c792f6140b1dTimo Sirainenstatic ssize_t read_more(struct seekable_istream *sstream)
16834f18f903048c772112838c015051642a0e77Timo Sirainen while ((ret = i_stream_read(sstream->cur_input)) == -1) {
if (size != 0)
return size;
return ret;
const unsigned char *data;
if (size == 0) {
return TRUE;
if (!have_space)
return FALSE;
return TRUE;
void *data;
const unsigned char *data;
return ret;
i_unreached();
return ret;
return ret;
if (ret <= 0) {
i_unreached();
return ret;
if (ret <= 0) {
return ret;
if (ret == 0) {
static struct istream_snapshot *
return prev_snapshot;
struct istream *
const unsigned char *data;
unsigned int count;
if (size > 0) {
unsigned int count;
return FALSE;
return TRUE;
struct istream *
void *context)
int fd;
return fd;
struct istream *
const char *temp_path_prefix)
return stream;