dovecot-2.2: lib: Added istream-unix for reading fd sockets via ...
dovecot at dovecot.org
dovecot at dovecot.org
Sat Apr 25 08:24:40 UTC 2015
details: http://hg.dovecot.org/dovecot-2.2/rev/21a2ce6f8f37
changeset: 18481:21a2ce6f8f37
user: Timo Sirainen <tss at iki.fi>
date: Sat Apr 25 11:23:00 2015 +0300
description:
lib: Added istream-unix for reading fd sockets via istream.
diffstat:
src/lib/Makefile.am | 4 +
src/lib/istream-file-private.h | 23 ++++
src/lib/istream-file.c | 36 +++----
src/lib/istream-unix.c | 105 ++++++++++++++++++++++
src/lib/istream-unix.h | 15 +++
src/lib/test-istream-unix.c | 190 +++++++++++++++++++++++++++++++++++++++++
src/lib/test-lib.c | 1 +
src/lib/test-lib.h | 1 +
8 files changed, 355 insertions(+), 20 deletions(-)
diffs (truncated from 497 to 300 lines):
diff -r 1c275f718758 -r 21a2ce6f8f37 src/lib/Makefile.am
--- a/src/lib/Makefile.am Sat Apr 25 11:22:39 2015 +0300
+++ b/src/lib/Makefile.am Sat Apr 25 11:23:00 2015 +0300
@@ -74,6 +74,7 @@
istream-sized.c \
istream-tee.c \
istream-timeout.c \
+ istream-unix.c \
ioloop.c \
ioloop-iolist.c \
ioloop-notify-none.c \
@@ -200,6 +201,7 @@
istream-chain.h \
istream-concat.h \
istream-crlf.h \
+ istream-file-private.h \
istream-hash.h \
istream-jsonstr.h \
istream-private.h \
@@ -208,6 +210,7 @@
istream-sized.h \
istream-tee.h \
istream-timeout.h \
+ istream-unix.h \
ioloop.h \
ioloop-iolist.h \
ioloop-private.h \
@@ -302,6 +305,7 @@
test-istream-crlf.c \
test-istream-seekable.c \
test-istream-tee.c \
+ test-istream-unix.c \
test-json-parser.c \
test-json-tree.c \
test-llist.c \
diff -r 1c275f718758 -r 21a2ce6f8f37 src/lib/istream-file-private.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib/istream-file-private.h Sat Apr 25 11:23:00 2015 +0300
@@ -0,0 +1,23 @@
+#ifndef ISTREAM_FILE_PRIVATE_H
+#define ISTREAM_FILE_PRIVATE_H
+
+#include "istream-private.h"
+
+struct file_istream {
+ struct istream_private istream;
+
+ uoff_t skip_left;
+
+ unsigned int file:1;
+ unsigned int autoclose_fd:1;
+ unsigned int seen_eof:1;
+};
+
+struct istream *
+i_stream_create_file_common(struct file_istream *fstream,
+ int fd, const char *path,
+ size_t max_buffer_size, bool autoclose_fd);
+ssize_t i_stream_file_read(struct istream_private *stream);
+void i_stream_file_close(struct iostream_private *stream, bool close_parent);
+
+#endif
diff -r 1c275f718758 -r 21a2ce6f8f37 src/lib/istream-file.c
--- a/src/lib/istream-file.c Sat Apr 25 11:22:39 2015 +0300
+++ b/src/lib/istream-file.c Sat Apr 25 11:23:00 2015 +0300
@@ -4,7 +4,7 @@
#include "lib.h"
#include "ioloop.h"
-#include "istream-private.h"
+#include "istream-file-private.h"
#include "net.h"
#include <time.h>
@@ -12,18 +12,8 @@
#include <fcntl.h>
#include <sys/stat.h>
-struct file_istream {
- struct istream_private istream;
-
- uoff_t skip_left;
-
- unsigned int file:1;
- unsigned int autoclose_fd:1;
- unsigned int seen_eof:1;
-};
-
-static void i_stream_file_close(struct iostream_private *stream,
- bool close_parent ATTR_UNUSED)
+void i_stream_file_close(struct iostream_private *stream,
+ bool close_parent ATTR_UNUSED)
{
struct file_istream *fstream = (struct file_istream *)stream;
struct istream_private *_stream = (struct istream_private *)stream;
@@ -51,7 +41,7 @@
return 0;
}
-static ssize_t i_stream_file_read(struct istream_private *stream)
+ssize_t i_stream_file_read(struct istream_private *stream)
{
struct file_istream *fstream = (struct file_istream *) stream;
uoff_t offset;
@@ -183,16 +173,15 @@
return 0;
}
-static struct istream *
-i_stream_create_file_common(int fd, const char *path,
+struct istream *
+i_stream_create_file_common(struct file_istream *fstream,
+ int fd, const char *path,
size_t max_buffer_size, bool autoclose_fd)
{
- struct file_istream *fstream;
struct istream *input;
struct stat st;
bool is_file;
- fstream = i_new(struct file_istream, 1);
fstream->autoclose_fd = autoclose_fd;
fstream->istream.iostream.close = i_stream_file_close;
@@ -235,9 +224,13 @@
struct istream *i_stream_create_fd(int fd, size_t max_buffer_size,
bool autoclose_fd)
{
+ struct file_istream *fstream;
+
i_assert(fd != -1);
- return i_stream_create_file_common(fd, NULL, max_buffer_size, autoclose_fd);
+ fstream = i_new(struct file_istream, 1);
+ return i_stream_create_file_common(fstream, fd, NULL,
+ max_buffer_size, autoclose_fd);
}
struct istream *i_stream_create_fd_autoclose(int *fd, size_t max_buffer_size)
@@ -251,9 +244,12 @@
struct istream *i_stream_create_file(const char *path, size_t max_buffer_size)
{
+ struct file_istream *fstream;
struct istream *input;
- input = i_stream_create_file_common(-1, path, max_buffer_size, TRUE);
+ fstream = i_new(struct file_istream, 1);
+ input = i_stream_create_file_common(fstream, -1, path,
+ max_buffer_size, TRUE);
i_stream_set_name(input, path);
return input;
}
diff -r 1c275f718758 -r 21a2ce6f8f37 src/lib/istream-unix.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib/istream-unix.c Sat Apr 25 11:23:00 2015 +0300
@@ -0,0 +1,105 @@
+/* Copyright (c) 2014 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "fdpass.h"
+#include "istream-file-private.h"
+#include "istream-unix.h"
+
+struct unix_istream {
+ struct file_istream fstream;
+ bool next_read_fd;
+ int read_fd;
+};
+
+static void
+i_stream_unix_close(struct iostream_private *stream, bool close_parent)
+{
+ struct unix_istream *ustream = (struct unix_istream *)stream;
+
+ if (ustream->read_fd != -1)
+ i_close_fd(&ustream->read_fd);
+ i_stream_file_close(stream, close_parent);
+}
+
+static ssize_t i_stream_unix_read(struct istream_private *stream)
+{
+ struct unix_istream *ustream = (struct unix_istream *)stream;
+ size_t size;
+ ssize_t ret;
+
+ if (!ustream->next_read_fd)
+ return i_stream_file_read(stream);
+
+ i_assert(ustream->read_fd == -1);
+ i_assert(ustream->fstream.skip_left == 0); /* not supported here.. */
+ if (!i_stream_try_alloc(stream, 1, &size))
+ return -2;
+
+ do {
+ ret = fd_read(stream->fd,
+ stream->w_buffer + stream->pos, size,
+ &ustream->read_fd);
+ } while (unlikely(ret < 0 && errno == EINTR &&
+ stream->istream.blocking));
+ if (ustream->read_fd != -1)
+ ustream->next_read_fd = FALSE;
+
+ if (unlikely(ret < 0)) {
+ if (errno == EINTR || errno == EAGAIN) {
+ i_assert(!stream->istream.blocking);
+ return 0;
+ } else {
+ i_assert(errno != 0);
+ /* if we get EBADF for a valid fd, it means something's
+ really wrong and we'd better just crash. */
+ i_assert(errno != EBADF);
+ stream->istream.stream_errno = errno;
+ return -1;
+ }
+ }
+ stream->pos += ret;
+ return ret;
+}
+
+struct istream *i_stream_create_unix(int fd, size_t max_buffer_size)
+{
+ struct unix_istream *ustream;
+ struct istream *input;
+
+ i_assert(fd != -1);
+
+ ustream = i_new(struct unix_istream, 1);
+ ustream->read_fd = -1;
+ input = i_stream_create_file_common(&ustream->fstream, fd, NULL,
+ max_buffer_size, FALSE);
+ input->real_stream->iostream.close = i_stream_unix_close;
+ input->real_stream->read = i_stream_unix_read;
+ return input;
+}
+
+void i_stream_unix_set_read_fd(struct istream *input)
+{
+ struct unix_istream *ustream =
+ (struct unix_istream *)input->real_stream;
+
+ ustream->next_read_fd = TRUE;
+}
+
+void i_stream_unix_unset_read_fd(struct istream *input)
+{
+ struct unix_istream *ustream =
+ (struct unix_istream *)input->real_stream;
+
+ ustream->next_read_fd = FALSE;
+}
+
+int i_stream_unix_get_read_fd(struct istream *input)
+{
+ struct unix_istream *ustream =
+ (struct unix_istream *)input->real_stream;
+ int fd;
+
+ fd = ustream->read_fd;
+ ustream->read_fd = -1;
+ return fd;
+}
diff -r 1c275f718758 -r 21a2ce6f8f37 src/lib/istream-unix.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib/istream-unix.h Sat Apr 25 11:23:00 2015 +0300
@@ -0,0 +1,15 @@
+#ifndef ISTREAM_UNIX_H
+#define ISTREAM_UNIX_H
+
+struct istream *i_stream_create_unix(int fd, size_t max_buffer_size);
+/* Start trying to read a file descriptor from the UNIX socket. */
+void i_stream_unix_set_read_fd(struct istream *input);
+/* Stop trying to read a file descriptor from the UNIX socket. */
+void i_stream_unix_unset_read_fd(struct istream *input);
+/* Returns the fd that the last i_stream_read() received, or -1 if no fd
+ was received. This function must be called before
+ i_stream_unix_set_read_fd() is called again after successfully receiving
+ a file descriptor. */
+int i_stream_unix_get_read_fd(struct istream *input);
+
+#endif
diff -r 1c275f718758 -r 21a2ce6f8f37 src/lib/test-istream-unix.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib/test-istream-unix.c Sat Apr 25 11:23:00 2015 +0300
@@ -0,0 +1,190 @@
+/* Copyright (c) 2015 Dovecot authors, see the included COPYING file */
+
+#include "test-lib.h"
+#include "net.h"
+#include "fd-set-nonblock.h"
+#include "fdpass.h"
+#include "istream.h"
+#include "istream-unix.h"
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
+static int send_fd, send_fd2;
+
More information about the dovecot-cvs
mailing list