bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2002-2018 Dovecot authors, see the included COPYING file */
b565a6a7a66fb9f224d00c06a950e3c1c585c18eTimo Sirainen
b565a6a7a66fb9f224d00c06a950e3c1c585c18eTimo Sirainen#include "lib.h"
b565a6a7a66fb9f224d00c06a950e3c1c585c18eTimo Sirainen#include "buffer.h"
0536ccb51d41e3078c3a9fa33e509fb4b2420f95Timo Sirainen#include "ostream-private.h"
b565a6a7a66fb9f224d00c06a950e3c1c585c18eTimo Sirainen
b565a6a7a66fb9f224d00c06a950e3c1c585c18eTimo Sirainenstruct buffer_ostream {
b565a6a7a66fb9f224d00c06a950e3c1c585c18eTimo Sirainen struct ostream_private ostream;
b565a6a7a66fb9f224d00c06a950e3c1c585c18eTimo Sirainen buffer_t *buf;
9929820d587fb6aa527a6baf89267b06950921c2Timo Sirainen bool seeked;
b565a6a7a66fb9f224d00c06a950e3c1c585c18eTimo Sirainen};
b565a6a7a66fb9f224d00c06a950e3c1c585c18eTimo Sirainen
b565a6a7a66fb9f224d00c06a950e3c1c585c18eTimo Sirainenstatic int o_stream_buffer_seek(struct ostream_private *stream, uoff_t offset)
b565a6a7a66fb9f224d00c06a950e3c1c585c18eTimo Sirainen{
9929820d587fb6aa527a6baf89267b06950921c2Timo Sirainen struct buffer_ostream *bstream = (struct buffer_ostream *)stream;
9929820d587fb6aa527a6baf89267b06950921c2Timo Sirainen
9929820d587fb6aa527a6baf89267b06950921c2Timo Sirainen bstream->seeked = TRUE;
b565a6a7a66fb9f224d00c06a950e3c1c585c18eTimo Sirainen stream->ostream.offset = offset;
b565a6a7a66fb9f224d00c06a950e3c1c585c18eTimo Sirainen return 1;
b565a6a7a66fb9f224d00c06a950e3c1c585c18eTimo Sirainen}
b565a6a7a66fb9f224d00c06a950e3c1c585c18eTimo Sirainen
b565a6a7a66fb9f224d00c06a950e3c1c585c18eTimo Sirainenstatic int
b565a6a7a66fb9f224d00c06a950e3c1c585c18eTimo Siraineno_stream_buffer_write_at(struct ostream_private *stream,
b565a6a7a66fb9f224d00c06a950e3c1c585c18eTimo Sirainen const void *data, size_t size, uoff_t offset)
b565a6a7a66fb9f224d00c06a950e3c1c585c18eTimo Sirainen{
b565a6a7a66fb9f224d00c06a950e3c1c585c18eTimo Sirainen struct buffer_ostream *bstream = (struct buffer_ostream *)stream;
b565a6a7a66fb9f224d00c06a950e3c1c585c18eTimo Sirainen
b565a6a7a66fb9f224d00c06a950e3c1c585c18eTimo Sirainen buffer_write(bstream->buf, offset, data, size);
b565a6a7a66fb9f224d00c06a950e3c1c585c18eTimo Sirainen return 0;
b565a6a7a66fb9f224d00c06a950e3c1c585c18eTimo Sirainen}
b565a6a7a66fb9f224d00c06a950e3c1c585c18eTimo Sirainen
b565a6a7a66fb9f224d00c06a950e3c1c585c18eTimo Sirainenstatic ssize_t
b565a6a7a66fb9f224d00c06a950e3c1c585c18eTimo Siraineno_stream_buffer_sendv(struct ostream_private *stream,
b565a6a7a66fb9f224d00c06a950e3c1c585c18eTimo Sirainen const struct const_iovec *iov, unsigned int iov_count)
b565a6a7a66fb9f224d00c06a950e3c1c585c18eTimo Sirainen{
b565a6a7a66fb9f224d00c06a950e3c1c585c18eTimo Sirainen struct buffer_ostream *bstream = (struct buffer_ostream *)stream;
9929820d587fb6aa527a6baf89267b06950921c2Timo Sirainen size_t left, n, offset;
b565a6a7a66fb9f224d00c06a950e3c1c585c18eTimo Sirainen ssize_t ret = 0;
b565a6a7a66fb9f224d00c06a950e3c1c585c18eTimo Sirainen unsigned int i;
b565a6a7a66fb9f224d00c06a950e3c1c585c18eTimo Sirainen
9929820d587fb6aa527a6baf89267b06950921c2Timo Sirainen offset = bstream->seeked ? stream->ostream.offset : bstream->buf->used;
9929820d587fb6aa527a6baf89267b06950921c2Timo Sirainen
b565a6a7a66fb9f224d00c06a950e3c1c585c18eTimo Sirainen for (i = 0; i < iov_count; i++) {
8f32e59200da904613506f5649ffa4d9f5989cebTimo Sirainen left = bstream->ostream.max_buffer_size -
8f32e59200da904613506f5649ffa4d9f5989cebTimo Sirainen stream->ostream.offset;
b565a6a7a66fb9f224d00c06a950e3c1c585c18eTimo Sirainen n = I_MIN(left, iov[i].iov_len);
9929820d587fb6aa527a6baf89267b06950921c2Timo Sirainen buffer_write(bstream->buf, offset, iov[i].iov_base, n);
9929820d587fb6aa527a6baf89267b06950921c2Timo Sirainen stream->ostream.offset += n; offset += n;
b565a6a7a66fb9f224d00c06a950e3c1c585c18eTimo Sirainen ret += n;
b565a6a7a66fb9f224d00c06a950e3c1c585c18eTimo Sirainen if (n != iov[i].iov_len)
b565a6a7a66fb9f224d00c06a950e3c1c585c18eTimo Sirainen break;
b565a6a7a66fb9f224d00c06a950e3c1c585c18eTimo Sirainen }
b565a6a7a66fb9f224d00c06a950e3c1c585c18eTimo Sirainen return ret;
b565a6a7a66fb9f224d00c06a950e3c1c585c18eTimo Sirainen}
b565a6a7a66fb9f224d00c06a950e3c1c585c18eTimo Sirainen
176fd2cdb19937915c728b93fb1a73c8ae91a720Stephan Boschstatic size_t
176fd2cdb19937915c728b93fb1a73c8ae91a720Stephan Boscho_stream_buffer_get_used_size(const struct ostream_private *stream)
176fd2cdb19937915c728b93fb1a73c8ae91a720Stephan Bosch{
176fd2cdb19937915c728b93fb1a73c8ae91a720Stephan Bosch struct buffer_ostream *bstream = (struct buffer_ostream *)stream;
176fd2cdb19937915c728b93fb1a73c8ae91a720Stephan Bosch
176fd2cdb19937915c728b93fb1a73c8ae91a720Stephan Bosch return bstream->buf->used;
176fd2cdb19937915c728b93fb1a73c8ae91a720Stephan Bosch}
176fd2cdb19937915c728b93fb1a73c8ae91a720Stephan Bosch
b565a6a7a66fb9f224d00c06a950e3c1c585c18eTimo Sirainenstruct ostream *o_stream_create_buffer(buffer_t *buf)
b565a6a7a66fb9f224d00c06a950e3c1c585c18eTimo Sirainen{
b565a6a7a66fb9f224d00c06a950e3c1c585c18eTimo Sirainen struct buffer_ostream *bstream;
9a755930537f13e9746c4fc8c1bc42a83e52275eTimo Sirainen struct ostream *output;
b565a6a7a66fb9f224d00c06a950e3c1c585c18eTimo Sirainen
b565a6a7a66fb9f224d00c06a950e3c1c585c18eTimo Sirainen bstream = i_new(struct buffer_ostream, 1);
a067446575cf5ce63f4a64fa0eb4aac16e591e89Timo Sirainen /* we don't set buffer as blocking, because if max_buffer_size is
a067446575cf5ce63f4a64fa0eb4aac16e591e89Timo Sirainen changed it can get truncated. this is used in various places in
a067446575cf5ce63f4a64fa0eb4aac16e591e89Timo Sirainen unit tests. */
8f32e59200da904613506f5649ffa4d9f5989cebTimo Sirainen bstream->ostream.max_buffer_size = (size_t)-1;
b565a6a7a66fb9f224d00c06a950e3c1c585c18eTimo Sirainen bstream->ostream.seek = o_stream_buffer_seek;
b565a6a7a66fb9f224d00c06a950e3c1c585c18eTimo Sirainen bstream->ostream.sendv = o_stream_buffer_sendv;
b565a6a7a66fb9f224d00c06a950e3c1c585c18eTimo Sirainen bstream->ostream.write_at = o_stream_buffer_write_at;
176fd2cdb19937915c728b93fb1a73c8ae91a720Stephan Bosch bstream->ostream.get_used_size = o_stream_buffer_get_used_size;
b565a6a7a66fb9f224d00c06a950e3c1c585c18eTimo Sirainen
b565a6a7a66fb9f224d00c06a950e3c1c585c18eTimo Sirainen bstream->buf = buf;
8b247780e911909a9fdc47f69ce6d1478902ad98Timo Sirainen output = o_stream_create(&bstream->ostream, NULL, -1);
9a755930537f13e9746c4fc8c1bc42a83e52275eTimo Sirainen o_stream_set_name(output, "(buffer)");
9a755930537f13e9746c4fc8c1bc42a83e52275eTimo Sirainen return output;
b565a6a7a66fb9f224d00c06a950e3c1c585c18eTimo Sirainen}