FIFO: Implement FION{BIO,READ}, B_SET_[NON]BLOCKING_IO ioctls

This commit is contained in:
Ingo Weinhold 2013-11-25 15:50:26 +01:00
parent fd0bfd5593
commit 8019fdbab8

View File

@ -11,6 +11,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <new>
@ -24,6 +25,7 @@
#include <khash.h>
#include <lock.h>
#include <select_sync_pool.h>
#include <syscall_restart.h>
#include <team.h>
#include <thread.h>
#include <util/DoublyLinkedList.h>
@ -241,6 +243,14 @@ private:
struct file_cookie {
int open_mode;
// guarded by Inode::fRequestLock
void SetNonBlocking(bool nonBlocking)
{
if (nonBlocking)
open_mode |= O_NONBLOCK;
else
open_mode &= ~(int)O_NONBLOCK;
}
};
@ -1059,12 +1069,65 @@ fifo_write_stat(fs_volume* volume, fs_vnode* vnode, const struct ::stat* st,
static status_t
fifo_ioctl(fs_volume* _volume, fs_vnode* _vnode, void* _cookie, uint32 op,
fifo_ioctl(fs_volume* _volume, fs_vnode* _node, void* _cookie, uint32 op,
void* buffer, size_t length)
{
file_cookie* cookie = (file_cookie*)_cookie;
Inode* inode = (Inode*)_node->private_node;
TRACE("fifo_ioctl: vnode %p, cookie %p, op %ld, buf %p, len %ld\n",
_vnode, _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)
return B_BAD_VALUE;
MutexLocker locker(inode->RequestLock());
int available = (int)inode->BytesAvailable();
locker.Unlock();
if (is_called_via_syscall()) {
if (!IS_USER_ADDRESS(buffer)
|| user_memcpy(buffer, &available, sizeof(available))
!= B_OK) {
return B_BAD_ADDRESS;
}
} else
*(int*)buffer = available;
return B_OK;
}
case B_SET_BLOCKING_IO:
case B_SET_NONBLOCKING_IO:
{
MutexLocker locker(inode->RequestLock());
cookie->SetNonBlocking(op == B_SET_NONBLOCKING_IO);
return B_OK;
}
}
return EINVAL;
}