⛏️ index : haiku.git

author Augustin Cavalier <waddlesplash@gmail.com> 2026-01-08 16:31:21.0 -05:00:00
committer Augustin Cavalier <waddlesplash@gmail.com> 2026-01-08 16:31:21.0 -05:00:00
commit
f1f209415bfb4d7ad8c9eecf8cde2bff519a91ca [patch]
tree
62c78d83789d23db5e52e92125f0d58fc42ba192
parent
7d234f26de8caf77e9b3b0f1278d6e815e27c9f1
download
f1f209415bfb4d7ad8c9eecf8cde2bff519a91ca.tar.gz

kernel/fs: Relocate and consolidate open mode checks.

 * get_new_fd is actually too late for the O_TRUNC one: we will
   have already called the vnode open() hook by then. So, we
   need to do that in open_vnode.

 * Move checks to a new static helper method, and invoke it
   in all relevant places.

 * Delete now-redundant O_NOFOLLOW checks.

Diff

 src/system/kernel/fs/vfs.cpp | 44 ++++++++++++++++++++++++++------------------
 1 file changed, 26 insertions(+), 18 deletions(-)

diff --git a/src/system/kernel/fs/vfs.cpp b/src/system/kernel/fs/vfs.cpp
index 01af52d..97e73fa 100644
--- a/src/system/kernel/fs/vfs.cpp
+++ b/src/system/kernel/fs/vfs.cpp
@@ -2849,11 +2849,6 @@
			&& (ops == &sFileOps || ops == &sDirectoryOps))
		return B_BUSY;

	if ((openMode & O_RDWR) != 0 && (openMode & O_WRONLY) != 0)
		return B_BAD_VALUE;
	if ((openMode & O_RWMASK) == O_RDONLY && (openMode & O_TRUNC) != 0)
		return B_NOT_ALLOWED;

	descriptor = alloc_fd();
	if (!descriptor)
		return B_NO_MEMORY;
@@ -5407,6 +5402,21 @@


//	#pragma mark - fd_ops implementations


static status_t
check_open_mode(struct vnode* vnode, int openMode)
{
	if ((openMode & O_RDWR) != 0 && (openMode & O_WRONLY) != 0)
		return B_BAD_VALUE;
	if ((openMode & O_RWMASK) == O_RDONLY && (openMode & O_TRUNC) != 0)
		return B_NOT_ALLOWED;

	if ((openMode & O_NOFOLLOW) != 0 && S_ISLNK(vnode->Type()))
		return B_LINK_LIMIT;

	return B_OK;
}


/*!
@@ -5416,8 +5426,12 @@
static int
open_vnode(struct vnode* vnode, int openMode, bool kernel)
{
	status_t status = check_open_mode(vnode, openMode);
	if (status != B_OK)
		return status;

	void* cookie;
	status_t status = FS_CALL(vnode, open, openMode, &cookie);
	status = FS_CALL(vnode, open, openMode, &cookie);
	if (status != B_OK)
		return status;

@@ -5498,8 +5512,6 @@
			}

			if (!create) {
				if ((openMode & O_NOFOLLOW) != 0 && S_ISLNK(vnode->Type()))
					return B_LINK_LIMIT;
				if (S_ISDIR(vnode->Type()))
					return B_IS_A_DIRECTORY;

@@ -5668,9 +5680,6 @@
	if (status != B_OK)
		return status;

	if ((openMode & O_NOFOLLOW) != 0 && S_ISLNK(vnode->Type()))
		return B_LINK_LIMIT;

	int newFD = open_vnode(vnode.Get(), openMode, kernel);
	if (newFD >= 0) {
		cache_node_opened(vnode.Get(), vnode->cache, mountID,
@@ -5699,9 +5708,6 @@
		&parentID, kernel);
	if (status != B_OK)
		return status;

	if ((openMode & O_NOFOLLOW) != 0 && S_ISLNK(vnode->Type()))
		return B_LINK_LIMIT;

	// open the vnode
	int newFD = open_vnode(vnode.Get(), openMode, kernel);
@@ -6904,8 +6910,9 @@
	if (status != B_OK)
		return status;

	if ((openMode & O_NOFOLLOW) != 0 && S_ISLNK(vnode->Type()))
		return B_LINK_LIMIT;
	status = check_open_mode(vnode.Get(), openMode);
	if (status != B_OK)
		return status;

	if (!HAS_FS_CALL(vnode, create_attr))
		return B_READ_ONLY_DEVICE;
@@ -6945,8 +6952,9 @@
	if (status != B_OK)
		return status;

	if ((openMode & O_NOFOLLOW) != 0 && S_ISLNK(vnode->Type()))
		return B_LINK_LIMIT;
	status = check_open_mode(vnode.Get(), openMode);
	if (status != B_OK)
		return status;

	if (!HAS_FS_CALL(vnode, open_attr))
		return B_UNSUPPORTED;