From 45383846d8d9372d325cb984637c9f2fb37c2c25 Mon Sep 17 00:00:00 2001 From: Augustin Cavalier Date: Mon, 27 May 2024 20:45:28 -0400 Subject: [PATCH] kernel/fs: Translate ioctl(FIONBIO) into fcntl(F_SETFL). This way, FIONBIO and O_NONBLOCK will no longer get out of sync, and additionally, FIONBIO can be used to change non-blocking status of regular (non-socket) FDs, too (which some applications seem to take advantage of, to avoid needing to fetch the open_mode before calling fcntl.) Change-Id: Id894fe76c79ac373c0121a003d68180a3d9b6560 Reviewed-on: https://review.haiku-os.org/c/haiku/+/7697 Tested-by: Commit checker robot Reviewed-by: waddlesplash --- .../kernel/network/stack/net_socket.cpp | 18 ---------------- src/system/kernel/fs/fd.cpp | 21 +++++++++++++++++++ src/system/kernel/fs/fifo.cpp | 19 ----------------- 3 files changed, 21 insertions(+), 37 deletions(-) diff --git a/src/add-ons/kernel/network/stack/net_socket.cpp b/src/add-ons/kernel/network/stack/net_socket.cpp index 981111433f..f7e169ef55 100644 --- a/src/add-ons/kernel/network/stack/net_socket.cpp +++ b/src/add-ons/kernel/network/stack/net_socket.cpp @@ -459,24 +459,6 @@ status_t socket_control(net_socket* socket, uint32 op, void* data, size_t length) { switch (op) { - case FIONBIO: - { - if (data == NULL) - return B_BAD_VALUE; - - int value; - if (is_syscall()) { - if (!IS_USER_ADDRESS(data) - || user_memcpy(&value, data, sizeof(int)) != B_OK) { - return B_BAD_ADDRESS; - } - } else - value = *(int*)data; - - return socket_setsockopt(socket, SOL_SOCKET, SO_NONBLOCK, &value, - sizeof(int)); - } - case FIONREAD: { if (data == NULL || (socket->options & SO_ACCEPTCONN) != 0) diff --git a/src/system/kernel/fs/fd.cpp b/src/system/kernel/fs/fd.cpp index 406269b9a9..9ccb342aaa 100644 --- a/src/system/kernel/fs/fd.cpp +++ b/src/system/kernel/fs/fd.cpp @@ -12,6 +12,7 @@ #include #include +#include #include @@ -472,6 +473,26 @@ fd_ioctl(bool kernelFD, int fd, uint32 op, void* buffer, size_t length) if (!descriptor.IsSet()) return B_FILE_ERROR; + // Special case: translate FIONBIO into fcntl(F_SETFL). + if (op == FIONBIO) { + if (buffer == NULL) + return B_BAD_VALUE; + + int value; + if (is_called_via_syscall()) { + if (!IS_USER_ADDRESS(buffer) + || user_memcpy(&value, buffer, sizeof(int)) != B_OK) { + return B_BAD_ADDRESS; + } + } else + value = *(int*)buffer; + + size_t argument = descriptor->open_mode & ~O_NONBLOCK; + argument |= (value ? O_NONBLOCK : 0); + + return (kernelFD ? _kern_fcntl : _user_fcntl)(fd, F_SETFL, argument); + } + status_t status; if (descriptor->ops->fd_ioctl) status = descriptor->ops->fd_ioctl(descriptor.Get(), op, buffer, length); diff --git a/src/system/kernel/fs/fifo.cpp b/src/system/kernel/fs/fifo.cpp index 3428076040..02441b8456 100644 --- a/src/system/kernel/fs/fifo.cpp +++ b/src/system/kernel/fs/fifo.cpp @@ -1065,25 +1065,6 @@ fifo_ioctl(fs_volume* _volume, fs_vnode* _node, void* _cookie, uint32 op, _node, _cookie, op, buffer, length); switch (op) { - case FIONBIO: - { - if (buffer == NULL) - return B_BAD_VALUE; - - int value; - if (is_called_via_syscall()) { - if (!IS_USER_ADDRESS(buffer) - || user_memcpy(&value, buffer, sizeof(int)) != B_OK) { - return B_BAD_ADDRESS; - } - } else - value = *(int*)buffer; - - MutexLocker locker(inode->RequestLock()); - cookie->SetNonBlocking(value != 0); - return B_OK; - } - case FIONREAD: { if (buffer == NULL)