From ce3b548077e1eb6f7eff7720bf8705bcbdbf97c7 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Thu, 21 Feb 2019 16:09:12 +0100 Subject: [PATCH] Kernel: Separate VFS stat() from open(). It was very confusing that you had to open a FileDescriptor in order to stat a file. This patch gives VFS a separate stat() function and uses it to implement the stat() and lstat() syscalls. --- Kernel/Process.cpp | 10 ++++------ Kernel/VirtualFileSystem.cpp | 16 +++++++++++++++- Kernel/VirtualFileSystem.h | 2 +- 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp index 607a1f5601..54be7f4c88 100644 --- a/Kernel/Process.cpp +++ b/Kernel/Process.cpp @@ -1217,10 +1217,9 @@ int Process::sys$lstat(const char* path, stat* statbuf) if (!validate_write_typed(statbuf)) return -EFAULT; int error; - auto descriptor = VFS::the().open(move(path), error, O_NOFOLLOW_NOERROR | O_DONT_OPEN_DEVICE, 0, *cwd_inode()); - if (!descriptor) + if (!VFS::the().stat(move(path), error, O_NOFOLLOW_NOERROR, *cwd_inode(), *statbuf)) return error; - return descriptor->fstat(statbuf); + return 0; } int Process::sys$stat(const char* path, stat* statbuf) @@ -1228,10 +1227,9 @@ int Process::sys$stat(const char* path, stat* statbuf) if (!validate_write_typed(statbuf)) return -EFAULT; int error; - auto descriptor = VFS::the().open(move(path), error, O_DONT_OPEN_DEVICE, 0, *cwd_inode()); - if (!descriptor) + if (!VFS::the().stat(move(path), error, 0, *cwd_inode(), *statbuf)) return error; - return descriptor->fstat(statbuf); + return 0; } int Process::sys$readlink(const char* path, char* buffer, size_t size) diff --git a/Kernel/VirtualFileSystem.cpp b/Kernel/VirtualFileSystem.cpp index 02530cbb1f..27c0c6d652 100644 --- a/Kernel/VirtualFileSystem.cpp +++ b/Kernel/VirtualFileSystem.cpp @@ -131,6 +131,17 @@ RetainPtr VFS::open(RetainPtr&& device, int& error, int return FileDescriptor::create(move(device)); } +bool VFS::stat(const String& path, int& error, int options, Inode& base, struct stat& statbuf) +{ + auto inode_id = resolve_path(path, base.identifier(), error, options); + if (!inode_id.is_valid()) + return false; + error = FileDescriptor::create(get_inode(inode_id))->fstat(&statbuf); + if (error) + return false; + return true; +} + RetainPtr VFS::open(const String& path, int& error, int options, mode_t mode, Inode& base) { auto inode_id = resolve_path(path, base.identifier(), error, options); @@ -145,7 +156,9 @@ RetainPtr VFS::open(const String& path, int& error, int options, } if (!inode) return nullptr; + auto metadata = inode->metadata(); + // NOTE: Read permission is a bit weird, since O_RDONLY == 0, // so we check if (NOT write_only OR read_and_write) if (!(options & O_WRONLY) || (options & O_RDWR)) { @@ -160,7 +173,8 @@ RetainPtr VFS::open(const String& path, int& error, int options, return nullptr; } } - if (!(options & O_DONT_OPEN_DEVICE) && metadata.is_device()) { + + if (metadata.is_device()) { auto it = m_devices.find(encoded_device(metadata.major_device, metadata.minor_device)); if (it == m_devices.end()) { kprintf("VFS::open: no such device %u,%u\n", metadata.major_device, metadata.minor_device); diff --git a/Kernel/VirtualFileSystem.h b/Kernel/VirtualFileSystem.h index ca822ce5fa..c90aa85b80 100644 --- a/Kernel/VirtualFileSystem.h +++ b/Kernel/VirtualFileSystem.h @@ -24,7 +24,6 @@ #define O_NOFOLLOW 00400000 #define O_CLOEXEC 02000000 #define O_NOFOLLOW_NOERROR 0x4000000 -#define O_DONT_OPEN_DEVICE 0x8000000 class Device; class FileDescriptor; @@ -70,6 +69,7 @@ public: bool unlink(const String& path, Inode& base, int& error); bool rmdir(const String& path, Inode& base, int& error); bool chmod(const String& path, mode_t, Inode& base, int& error); + bool stat(const String& path, int& error, int options, Inode& base, struct stat&); void register_device(Device&); void unregister_device(Device&);