Mercurial > dovecot > core-2.2
changeset 22101:dbb9b7c9ca9f
lib: Added ostream-unix for writing fd sockets via ostream.
author | Stephan Bosch <stephan@rename-it.nl> |
---|---|
date | Sat, 30 Apr 2016 12:50:53 +0200 |
parents | 4484220b090c |
children | af8d96508fad |
files | src/lib/Makefile.am src/lib/ostream-unix.c src/lib/ostream-unix.h |
diffstat | 3 files changed, 102 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib/Makefile.am Mon Jun 05 19:05:58 2017 +0300 +++ b/src/lib/Makefile.am Sat Apr 30 12:50:53 2016 +0200 @@ -116,6 +116,7 @@ ostream-hash.c \ ostream-null.c \ ostream-rawlog.c \ + ostream-unix.c \ pkcs5.c \ primes.c \ printf-format-fix.c \ @@ -255,6 +256,7 @@ ostream-private.h \ ostream-null.h \ ostream-rawlog.h \ + ostream-unix.h \ pkcs5.h \ primes.h \ printf-format-fix.h \
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/lib/ostream-unix.c Sat Apr 30 12:50:53 2016 +0200 @@ -0,0 +1,90 @@ +/* Copyright (c) 2015-2016 Dovecot authors, see the included COPYING file */ + +#include "lib.h" +#include "fdpass.h" +#include "ostream-file-private.h" +#include "ostream-unix.h" + +struct unix_ostream { + struct file_ostream fstream; + int write_fd; +}; + +static void +o_stream_unix_close(struct iostream_private *stream, bool close_parent) +{ + struct unix_ostream *ustream = (struct unix_ostream *)stream; + + if (ustream->write_fd != -1) + i_close_fd(&ustream->write_fd); + o_stream_file_close(stream, close_parent); +} + +static ssize_t o_stream_unix_writev(struct file_ostream *fstream, + const struct const_iovec *iov, + unsigned int iov_count) +{ + struct unix_ostream *ustream = (struct unix_ostream *)fstream; + size_t sent; + ssize_t ret; + + if (ustream->write_fd == -1) { + /* no fd */ + return o_stream_file_writev(fstream, iov, iov_count); + } + + /* send first iovec along with fd */ + if (iov_count == 0) + return 0; + i_assert(iov[0].iov_len > 0); + ret = fd_send(fstream->fd, ustream->write_fd, + iov[0].iov_base, iov[0].iov_len); + if (ret < 0) + return ret; + + /* update stream */ + sent = ret; + fstream->real_offset += sent; + + ustream->write_fd = -1; + + if (sent < iov[0].iov_len || iov_count == 1) { + /* caller will call us again to write the rest */ + return sent; + } + + /* send remaining iovecs */ + ret = o_stream_file_writev(fstream, &iov[1], iov_count-1); + if (ret < 0) + return (errno == EAGAIN || errno == EINTR ? (ssize_t)sent : ret); + sent += ret; + return sent; +} + +struct ostream *o_stream_create_unix(int fd, size_t max_buffer_size) +{ + struct unix_ostream *ustream; + struct ostream *output; + + i_assert(fd != -1); + + ustream = i_new(struct unix_ostream, 1); + ustream->write_fd = -1; + output = o_stream_create_file_common(&ustream->fstream, fd, + max_buffer_size, FALSE); + output->real_stream->iostream.close = o_stream_unix_close; + ustream->fstream.writev = o_stream_unix_writev; + + return output; +} + +bool o_stream_unix_write_fd(struct ostream *output, int fd) +{ + struct unix_ostream *ustream = + (struct unix_ostream *)output->real_stream; + + if (ustream->write_fd >= 0) + return FALSE; + ustream->write_fd = fd; + return TRUE; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/lib/ostream-unix.h Sat Apr 30 12:50:53 2016 +0200 @@ -0,0 +1,10 @@ +#ifndef OSTREAM_UNIX_H +#define OSTREAM_UNIX_H + +struct ostream *o_stream_create_unix(int fd, size_t max_buffer_size); +/* Write fd to UNIX socket along with the next outgoing data block. + Returns TRUE if fd is accepted, and FALSE if a previous fd still + needs to be sent. */ +bool o_stream_unix_write_fd(struct ostream *output, int fd); + +#endif