diff --git a/src/system/kernel/fs/fifo.cpp b/src/system/kernel/fs/fifo.cpp index 2b403bd800..bf42d02759 100644 --- a/src/system/kernel/fs/fifo.cpp +++ b/src/system/kernel/fs/fifo.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -24,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -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; }