From 22831033d03dc8676b5d12af3619d10a295cf8cd Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Sun, 6 Sep 2020 18:31:51 +0200 Subject: [PATCH] Kernel: Virtualize the File::stat() operation Instead of FileDescriptor branching on the type of File it's wrapping, add a File::stat() function that can be overridden to provide custom behavior for the stat syscalls. --- Kernel/FileSystem/FIFO.cpp | 7 +++++++ Kernel/FileSystem/FIFO.h | 1 + Kernel/FileSystem/File.h | 1 + Kernel/FileSystem/FileDescription.cpp | 19 +++++-------------- Kernel/Net/Socket.cpp | 7 +++++++ Kernel/Net/Socket.h | 13 +++++++------ 6 files changed, 28 insertions(+), 20 deletions(-) diff --git a/Kernel/FileSystem/FIFO.cpp b/Kernel/FileSystem/FIFO.cpp index 3b22a45c6a..3f9c1e33a1 100644 --- a/Kernel/FileSystem/FIFO.cpp +++ b/Kernel/FileSystem/FIFO.cpp @@ -166,4 +166,11 @@ String FIFO::absolute_path(const FileDescription&) const return String::format("fifo:%u", m_fifo_id); } +KResult FIFO::stat(::stat& st) const +{ + memset(&st, 0, sizeof(st)); + st.st_mode = S_IFIFO; + return KSuccess; +} + } diff --git a/Kernel/FileSystem/FIFO.h b/Kernel/FileSystem/FIFO.h index c41ee67ddb..81b04597f2 100644 --- a/Kernel/FileSystem/FIFO.h +++ b/Kernel/FileSystem/FIFO.h @@ -59,6 +59,7 @@ private: // ^File virtual KResultOr write(FileDescription&, size_t, const u8*, size_t) override; virtual KResultOr read(FileDescription&, size_t, u8*, size_t) override; + virtual KResult stat(::stat&) const override; virtual bool can_read(const FileDescription&, size_t) const override; virtual bool can_write(const FileDescription&, size_t) const override; virtual String absolute_path(const FileDescription&) const override; diff --git a/Kernel/FileSystem/File.h b/Kernel/FileSystem/File.h index 48efffed73..9d3a1c6073 100644 --- a/Kernel/FileSystem/File.h +++ b/Kernel/FileSystem/File.h @@ -78,6 +78,7 @@ public: virtual KResultOr write(FileDescription&, size_t, const u8*, size_t) = 0; virtual int ioctl(FileDescription&, unsigned request, FlatPtr arg); virtual KResultOr mmap(Process&, FileDescription&, VirtualAddress preferred_vaddr, size_t offset, size_t size, int prot, bool shared); + virtual KResult stat(::stat&) const { return KResult(-EBADF); } virtual String absolute_path(const FileDescription&) const = 0; diff --git a/Kernel/FileSystem/FileDescription.cpp b/Kernel/FileSystem/FileDescription.cpp index fae9868250..80153e6225 100644 --- a/Kernel/FileSystem/FileDescription.cpp +++ b/Kernel/FileSystem/FileDescription.cpp @@ -77,20 +77,11 @@ FileDescription::~FileDescription() KResult FileDescription::stat(::stat& buffer) { - if (is_fifo()) { - memset(&buffer, 0, sizeof(buffer)); - buffer.st_mode = S_IFIFO; - return KSuccess; - } - if (is_socket()) { - memset(&buffer, 0, sizeof(buffer)); - buffer.st_mode = S_IFSOCK; - return KSuccess; - } - - if (!m_inode) - return KResult(-EBADF); - return metadata().stat(buffer); + LOCKER(m_lock); + // FIXME: This is a little awkward, why can't we always forward to File::stat()? + if (m_inode) + return metadata().stat(buffer); + return m_file->stat(buffer); } off_t FileDescription::seek(off_t offset, int whence) diff --git a/Kernel/Net/Socket.cpp b/Kernel/Net/Socket.cpp index 42a657a06d..061068e3ec 100644 --- a/Kernel/Net/Socket.cpp +++ b/Kernel/Net/Socket.cpp @@ -220,4 +220,11 @@ KResult Socket::shutdown(int how) return KSuccess; } +KResult Socket::stat(::stat& st) const +{ + memset(&st, 0, sizeof(st)); + st.st_mode = S_IFSOCK; + return KSuccess; +} + } diff --git a/Kernel/Net/Socket.h b/Kernel/Net/Socket.h index 8f78c19e5e..b72fa5f837 100644 --- a/Kernel/Net/Socket.h +++ b/Kernel/Net/Socket.h @@ -58,9 +58,9 @@ public: bool is_shut_down_for_reading() const { return m_shut_down_for_reading; } enum class SetupState { - Unstarted, // we haven't tried to set the socket up yet + Unstarted, // we haven't tried to set the socket up yet InProgress, // we're in the process of setting things up - for TCP maybe we've sent a SYN packet - Completed, // the setup process is complete, but not necessarily successful + Completed, // the setup process is complete, but not necessarily successful }; enum class Role : u8 { @@ -126,6 +126,7 @@ public: // ^File virtual KResultOr read(FileDescription&, size_t, u8*, size_t) override final; virtual KResultOr write(FileDescription&, size_t, const u8*, size_t) override final; + virtual KResult stat(::stat&) const override; virtual String absolute_path(const FileDescription&) const override = 0; bool has_receive_timeout() const { return m_receive_timeout.tv_sec || m_receive_timeout.tv_usec; } @@ -144,8 +145,8 @@ protected: virtual const char* class_name() const override { return "Socket"; } - virtual void shut_down_for_reading() {} - virtual void shut_down_for_writing() {} + virtual void shut_down_for_reading() { } + virtual void shut_down_for_writing() { } Role m_role { Role::None }; @@ -175,10 +176,10 @@ private: NonnullRefPtrVector m_pending; }; -template +template class SocketHandle { public: - SocketHandle() {} + SocketHandle() { } SocketHandle(NonnullRefPtr&& socket) : m_socket(move(socket))