static status_t fifo_read(fs_volume* _volume, fs_vnode* _node, void* _cookie, off_t /*pos*/, void* buffer, size_t* _length) { file_cookie* cookie = (file_cookie*)_cookie; Inode* inode = (Inode*)_node->private_node; TRACE("fifo_read(vnode = %p, cookie = %p, length = %lu, mode = %d)\n", inode, cookie, *_length, cookie->open_mode); MutexLocker locker(inode->RequestLock()); if ((cookie->open_mode & O_RWMASK) != O_RDONLY) return B_NOT_ALLOWED; if (inode->IsActive() && inode->WriterCount() == 0) { // as long there is no writer, and the pipe is empty, // we always just return 0 to indicate end of file if (inode->BytesAvailable() == 0) { *_length = 0; return B_OK; } } // issue read request ReadRequest request(cookie); inode->AddReadRequest(request); TRACE(" issue read request %p\n", &request); size_t length = *_length; status_t status = inode->ReadDataFromBuffer(buffer, &length, (cookie->open_mode & O_NONBLOCK) != 0, is_called_via_syscall(), request); inode->RemoveReadRequest(request); inode->NotifyReadDone(); TRACE(" done reading request %p, length %zu\n", &request, length); if (length > 0) status = B_OK; *_length = length; return status; }
static status_t 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; }