From ac46a180d8c4048e65f8146009a191e73dbee76c Mon Sep 17 00:00:00 2001 From: Augustin Cavalier Date: Wed, 7 Jan 2026 14:02:46 -0500 Subject: [PATCH] kernel/fs: Check if the existing node is a directory in create_vnode. Otherwise, calling open(O_CREAT) on a path that exists but is a directory will succeed. Fixes Sortix os-test open-tmpdir-rdonly-creat. (Interestingly many other OSes also fail this test; only Linux, FreeBSD, Solaris, and Sortix, and now also Haiku, properly return EISDIR.) While at it, fix the doc comment, which appears to have been copied from open_vnode. --- src/system/kernel/fs/vfs.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/system/kernel/fs/vfs.cpp b/src/system/kernel/fs/vfs.cpp index 479becce15..01af52d2bd 100644 --- a/src/system/kernel/fs/vfs.cpp +++ b/src/system/kernel/fs/vfs.cpp @@ -5431,8 +5431,10 @@ open_vnode(struct vnode* vnode, int openMode, bool kernel) /*! - Calls fs_open() on the given vnode and returns a new - file descriptor for it + Creates a new regular file and returns a new file descriptor for it. + + If O_EXCL is not specified and an entry already exists at the path, + then that entry will be opened and returned instead. */ static int create_vnode(struct vnode* directory, const char* name, int openMode, @@ -5498,6 +5500,8 @@ create_vnode(struct vnode* directory, const char* name, int openMode, 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; int fd = open_vnode(vnode.Get(), openMode & ~O_CREAT, kernel); // on success keep the vnode reference for the FD