From adb48b5c9e980b86f70f98b3a2ed81c3857a9321 Mon Sep 17 00:00:00 2001 From: Emery Hemingway Date: Thu, 21 Jun 2018 09:42:17 +0200 Subject: [PATCH] Libc: MSG_PEEK support As discovered by Johannes Kliemann, peeking at buffered socket data using 'recv' and 'MSG_PEEK' is not supported. Read a "peek" control file from the socket directory to attempt to peek into buffers at the socket_fs. Support for every feature of POSIX sockets cannot be expected, but this one is trivial to implement. Fix #2875 --- repos/libports/src/lib/libc/socket_fs_plugin.cc | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/repos/libports/src/lib/libc/socket_fs_plugin.cc b/repos/libports/src/lib/libc/socket_fs_plugin.cc index 6590bc5295..5345ccb685 100644 --- a/repos/libports/src/lib/libc/socket_fs_plugin.cc +++ b/repos/libports/src/lib/libc/socket_fs_plugin.cc @@ -131,7 +131,7 @@ struct Libc::Socket_fs::Context : Plugin_context private: enum Fd : unsigned { - DATA, CONNECT, BIND, LISTEN, ACCEPT, LOCAL, REMOTE, MAX + DATA, PEEK, CONNECT, BIND, LISTEN, ACCEPT, LOCAL, REMOTE, MAX }; struct @@ -140,7 +140,7 @@ struct Libc::Socket_fs::Context : Plugin_context int num; File_descriptor *file; } _fd[Fd::MAX] = { - { "data", -1, nullptr }, + { "data", -1, nullptr }, { "peek", -1, nullptr }, { "connect", -1, nullptr }, { "bind", -1, nullptr }, { "listen", -1, nullptr }, { "accept", -1, nullptr }, { "local", -1, nullptr }, { "remote", -1, nullptr } @@ -205,6 +205,7 @@ struct Libc::Socket_fs::Context : Plugin_context } int data_fd() { return _fd_for_type(Fd::DATA, O_RDWR); } + int peek_fd() { return _fd_for_type(Fd::PEEK, O_RDONLY); } int connect_fd() { return _fd_for_type(Fd::CONNECT, O_RDWR); } int bind_fd() { return _fd_for_type(Fd::BIND, O_WRONLY); } int listen_fd() { return _fd_for_type(Fd::LISTEN, O_WRONLY); } @@ -751,9 +752,11 @@ static ssize_t do_recvfrom(File_descriptor *fd, /* TODO ENOTCONN */ /* TODO ECONNREFUSED */ + int data_fd = flags & MSG_PEEK ? context->peek_fd() : context->data_fd(); + try { - lseek(context->data_fd(), 0, 0); - ssize_t out_len = read(context->data_fd(), buf, len); + lseek(data_fd, 0, 0); + ssize_t out_len = read(data_fd, buf, len); return out_len; } catch (Socket_fs::Context::Inaccessible) { return Errno(EINVAL);