Explorar o código

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.
Andreas Kling %!s(int64=4) %!d(string=hai) anos
pai
achega
22831033d0

+ 7 - 0
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;
+}
+
 }

+ 1 - 0
Kernel/FileSystem/FIFO.h

@@ -59,6 +59,7 @@ private:
     // ^File
     virtual KResultOr<size_t> write(FileDescription&, size_t, const u8*, size_t) override;
     virtual KResultOr<size_t> 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;

+ 1 - 0
Kernel/FileSystem/File.h

@@ -78,6 +78,7 @@ public:
     virtual KResultOr<size_t> write(FileDescription&, size_t, const u8*, size_t) = 0;
     virtual int ioctl(FileDescription&, unsigned request, FlatPtr arg);
     virtual KResultOr<Region*> 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;
 

+ 5 - 14
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)

+ 7 - 0
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;
+}
+
 }

+ 7 - 6
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<size_t> read(FileDescription&, size_t, u8*, size_t) override final;
     virtual KResultOr<size_t> 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<Socket> m_pending;
 };
 
-template <typename SocketType>
+template<typename SocketType>
 class SocketHandle {
 public:
-    SocketHandle() {}
+    SocketHandle() { }
 
     SocketHandle(NonnullRefPtr<SocketType>&& socket)
         : m_socket(move(socket))