From 27fda3e46f1422503a08a3d34e4618778b2dc146 Mon Sep 17 00:00:00 2001 From: Augustin Cavalier Date: Thu, 30 Jun 2022 12:16:00 -0400 Subject: [PATCH] kernel/fifo: Properly support opening FIFOs in O_RDWR mode. While pipe() only supports a read end and a write end, named FIFOs are supposed to allow opening in read/write mode (which, indeed, is something the Fish shell seems to require.) The code that checks open_mode in the read/write routines was introduced all the way back in 2003 (2469f26dfc618dac7853c0de146df7872e60623f). At that time, the VFS did not do open_mode checks on FDs in the I/O syscalls, so these doubled as permissions checks. Now, however, the VFS does check that in common_user_io, so we can remove these entirely and let things behave as they should. Additionally, there is now also no reason to prevent select()ing on both events for the same FD independent of open_mode, so allow that too. Change-Id: Ib3cba76d18e91b7c00d1695e8d29dd47cae06b79 Reviewed-on: https://review.haiku-os.org/c/haiku/+/5427 Reviewed-by: waddlesplash --- src/system/kernel/fs/fifo.cpp | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/src/system/kernel/fs/fifo.cpp b/src/system/kernel/fs/fifo.cpp index a49b3f2eee..b6fb3f80b4 100644 --- a/src/system/kernel/fs/fifo.cpp +++ b/src/system/kernel/fs/fifo.cpp @@ -634,7 +634,7 @@ Inode::Open(int openMode) { MutexLocker locker(RequestLock()); - if ((openMode & O_ACCMODE) == O_WRONLY) + if ((openMode & O_ACCMODE) == O_WRONLY || (openMode & O_ACCMODE) == O_RDWR) fWriterCount++; if ((openMode & O_ACCMODE) == O_RDONLY || (openMode & O_ACCMODE) == O_RDWR) @@ -669,11 +669,12 @@ Inode::Close(file_cookie* cookie) request->Notify(B_FILE_ERROR); } - if ((openMode & O_ACCMODE) == O_WRONLY && --fWriterCount == 0) - NotifyEndClosed(true); + if ((openMode & O_ACCMODE) == O_WRONLY || (openMode & O_ACCMODE) == O_RDWR) { + if (--fWriterCount == 0) + NotifyEndClosed(true); + } - if ((openMode & O_ACCMODE) == O_RDONLY - || (openMode & O_ACCMODE) == O_RDWR) { + if ((openMode & O_ACCMODE) == O_RDONLY || (openMode & O_ACCMODE) == O_RDWR) { if (--fReaderCount == 0) NotifyEndClosed(false); } @@ -697,7 +698,7 @@ Inode::Select(uint8 event, selectsync* sync, int openMode) { bool writer = true; select_sync_pool** pool; - if ((openMode & O_RWMASK) == O_RDONLY) { + if (event == B_SELECT_READ || (openMode & O_RWMASK) == O_RDONLY) { pool = &fReadSelectSyncPool; writer = false; } else if ((openMode & O_RWMASK) == O_WRONLY) { @@ -938,9 +939,6 @@ fifo_read(fs_volume* _volume, fs_vnode* _node, void* _cookie, 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 @@ -987,9 +985,6 @@ fifo_write(fs_volume* _volume, fs_vnode* _node, void* _cookie, MutexLocker locker(inode->RequestLock()); - if ((cookie->open_mode & O_RWMASK) != O_WRONLY) - return B_NOT_ALLOWED; - size_t length = *_length; if (length == 0) return B_OK;