return 0;
}
+int o_stream_temp_move_to_memory(struct ostream *output)
+{
+ struct temp_ostream *tstream =
+ (struct temp_ostream *)output->real_stream;
+ unsigned char buf[IO_BLOCK_SIZE];
+ uoff_t offset = 0;
+ ssize_t ret = 0;
+
+ i_assert(tstream->buf == NULL);
+ tstream->buf = buffer_create_dynamic(default_pool, 8192);
+ while (offset < tstream->ostream.ostream.offset &&
+ (ret = pread(tstream->fd, buf, sizeof(buf), offset)) > 0) {
+ if ((size_t)ret > tstream->ostream.ostream.offset - offset)
+ ret = tstream->ostream.ostream.offset - offset;
+ buffer_append(tstream->buf, buf, ret);
+ offset += ret;
+ }
+ if (ret < 0) {
+ /* not really expecting this to happen */
+ i_error("iostream-temp %s: read(%s*) failed: %m",
+ o_stream_get_name(&tstream->ostream.ostream),
+ tstream->temp_path_prefix);
+ tstream->ostream.ostream.stream_errno = EIO;
+ return -1;
+ }
+ i_close_fd(&tstream->fd);
+ tstream->ostream.fd = -1;
+ return 0;
+}
+
static ssize_t
o_stream_temp_fd_sendv(struct temp_ostream *tstream,
const struct const_iovec *iov, unsigned int iov_count)
for (i = 0; i < iov_count; i++) {
if (write_full(tstream->fd, iov[i].iov_base, iov[i].iov_len) < 0) {
- tstream->ostream.ostream.stream_errno = errno;
- return -1;
+ i_error("iostream-temp %s: write(%s*) failed: %m - moving to memory",
+ o_stream_get_name(&tstream->ostream.ostream),
+ tstream->temp_path_prefix);
+ if (o_stream_temp_move_to_memory(&tstream->ostream.ostream) < 0)
+ return -1;
+ for (; i < iov_count; i++) {
+ buffer_append(tstream->buf, iov[i].iov_base, iov[i].iov_len);
+ bytes += iov[i].iov_len;
+ tstream->ostream.ostream.offset += iov[i].iov_len;
+ }
+ i_assert(tstream->fd_tried);
+ return bytes;
}
bytes += iov[i].iov_len;
tstream->ostream.ostream.offset += iov[i].iov_len;
test_end();
}
+static void test_iostream_temp_create_write_error(void)
+{
+ struct ostream *output;
+
+ test_begin("iostream_temp_create_sized() write error");
+ output = iostream_temp_create_sized(".", 0, "test", 1);
+
+ test_assert(o_stream_send(output, "123", 3) == 3);
+ test_assert(o_stream_get_fd(output) != -1);
+ test_assert(output->offset == 3);
+ test_assert(o_stream_temp_move_to_memory(output) == 0);
+ test_assert(o_stream_get_fd(output) == -1);
+ test_assert(o_stream_send(output, "45", 2) == 2);
+ test_assert(output->offset == 5);
+
+ const unsigned char *data;
+ size_t size;
+ struct istream *input = iostream_temp_finish(&output, 128);
+ test_assert(i_stream_read_bytes(input, &data, &size, 5) == 1 &&
+ memcmp(data, "12345", 5) == 0);
+ i_stream_destroy(&input);
+
+ test_end();
+}
+
static void test_iostream_temp_istream(void)
{
struct istream *input, *input2, *temp_input;
{
test_iostream_temp_create_sized_memory();
test_iostream_temp_create_sized_disk();
+ test_iostream_temp_create_write_error();
test_iostream_temp_istream();
}