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 <[email protected]> Reviewed-by: waddlesplash <[email protected]>
This commit is contained in:
committed by
waddlesplash
parent
e08f7fd12b
commit
45383846d8
@@ -459,24 +459,6 @@ status_t
|
|||||||
socket_control(net_socket* socket, uint32 op, void* data, size_t length)
|
socket_control(net_socket* socket, uint32 op, void* data, size_t length)
|
||||||
{
|
{
|
||||||
switch (op) {
|
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:
|
case FIONREAD:
|
||||||
{
|
{
|
||||||
if (data == NULL || (socket->options & SO_ACCEPTCONN) != 0)
|
if (data == NULL || (socket->options & SO_ACCEPTCONN) != 0)
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
|
||||||
#include <OS.h>
|
#include <OS.h>
|
||||||
|
|
||||||
@@ -472,6 +473,26 @@ fd_ioctl(bool kernelFD, int fd, uint32 op, void* buffer, size_t length)
|
|||||||
if (!descriptor.IsSet())
|
if (!descriptor.IsSet())
|
||||||
return B_FILE_ERROR;
|
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;
|
status_t status;
|
||||||
if (descriptor->ops->fd_ioctl)
|
if (descriptor->ops->fd_ioctl)
|
||||||
status = descriptor->ops->fd_ioctl(descriptor.Get(), op, buffer, length);
|
status = descriptor->ops->fd_ioctl(descriptor.Get(), op, buffer, length);
|
||||||
|
|||||||
@@ -1065,25 +1065,6 @@ fifo_ioctl(fs_volume* _volume, fs_vnode* _node, void* _cookie, uint32 op,
|
|||||||
_node, _cookie, op, buffer, length);
|
_node, _cookie, op, buffer, length);
|
||||||
|
|
||||||
switch (op) {
|
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:
|
case FIONREAD:
|
||||||
{
|
{
|
||||||
if (buffer == NULL)
|
if (buffer == NULL)
|
||||||
|
|||||||
Reference in New Issue
Block a user