diff options
author | Andreas Kling <awesomekling@gmail.com> | 2019-05-30 13:39:17 +0200 |
---|---|---|
committer | Andreas Kling <awesomekling@gmail.com> | 2019-05-30 13:39:17 +0200 |
commit | 08926e59b36dd46e4fad9db522d4a2192ede7263 (patch) | |
tree | fdf5cec7f831d5a33b35c86452533c094cb8d212 /Kernel/FileSystem | |
parent | 66c1a9be3b01a508adec71910164f84e3bbe3923 (diff) | |
download | serenity-08926e59b36dd46e4fad9db522d4a2192ede7263.zip |
Kernel: Add InodeFile, a File subclass for regular files.
Finally everything that can be held by a FileDescriptor actually inherits
from the File class.
Diffstat (limited to 'Kernel/FileSystem')
-rw-r--r-- | Kernel/FileSystem/FileDescriptor.cpp | 163 | ||||
-rw-r--r-- | Kernel/FileSystem/FileDescriptor.h | 12 | ||||
-rw-r--r-- | Kernel/FileSystem/InodeFile.cpp | 55 | ||||
-rw-r--r-- | Kernel/FileSystem/InodeFile.h | 38 |
4 files changed, 142 insertions, 126 deletions
diff --git a/Kernel/FileSystem/FileDescriptor.cpp b/Kernel/FileSystem/FileDescriptor.cpp index 24074afdc0..e76f7d7b6a 100644 --- a/Kernel/FileSystem/FileDescriptor.cpp +++ b/Kernel/FileSystem/FileDescriptor.cpp @@ -1,21 +1,22 @@ -#include "FileDescriptor.h" -#include <Kernel/FileSystem/FileSystem.h> -#include <Kernel/Devices/CharacterDevice.h> -#include <LibC/errno_numbers.h> -#include "UnixTypes.h" #include <AK/BufferStream.h> +#include <Kernel/Devices/BlockDevice.h> +#include <Kernel/Devices/CharacterDevice.h> #include <Kernel/FileSystem/FIFO.h> -#include <Kernel/TTY/TTY.h> -#include <Kernel/TTY/MasterPTY.h> +#include <Kernel/FileSystem/FileDescriptor.h> +#include <Kernel/FileSystem/FileSystem.h> +#include <Kernel/FileSystem/InodeFile.h> #include <Kernel/Net/Socket.h> #include <Kernel/Process.h> -#include <Kernel/Devices/BlockDevice.h> -#include <Kernel/VM/MemoryManager.h> #include <Kernel/SharedMemory.h> +#include <Kernel/TTY/MasterPTY.h> +#include <Kernel/TTY/TTY.h> +#include <Kernel/UnixTypes.h> +#include <Kernel/VM/MemoryManager.h> +#include <LibC/errno_numbers.h> Retained<FileDescriptor> FileDescriptor::create(RetainPtr<Inode>&& inode) { - return adopt(*new FileDescriptor(move(inode))); + return adopt(*new FileDescriptor(InodeFile::create(*inode))); } Retained<FileDescriptor> FileDescriptor::create(RetainPtr<File>&& file, SocketRole role) @@ -23,14 +24,11 @@ Retained<FileDescriptor> FileDescriptor::create(RetainPtr<File>&& file, SocketRo return adopt(*new FileDescriptor(move(file), role)); } -FileDescriptor::FileDescriptor(RetainPtr<Inode>&& inode) - : m_inode(move(inode)) -{ -} - FileDescriptor::FileDescriptor(RetainPtr<File>&& file, SocketRole role) : m_file(move(file)) { + if (m_file->is_inode()) + m_inode = static_cast<InodeFile&>(*m_file).inode(); set_socket_role(role); } @@ -40,10 +38,8 @@ FileDescriptor::~FileDescriptor() socket()->detach(*this); if (is_fifo()) static_cast<FIFO*>(m_file.ptr())->detach(m_fifo_direction); - if (m_file) { - m_file->close(); - m_file = nullptr; - } + m_file->close(); + m_file = nullptr; m_inode = nullptr; } @@ -65,12 +61,8 @@ Retained<FileDescriptor> FileDescriptor::clone() if (is_fifo()) { descriptor = fifo()->open_direction(m_fifo_direction); } else { - if (m_file) { - descriptor = FileDescriptor::create(m_file.copy_ref(), m_socket_role); - descriptor->m_inode = m_inode.copy_ref(); - } else { - descriptor = FileDescriptor::create(m_inode.copy_ref()); - } + descriptor = FileDescriptor::create(m_file.copy_ref(), m_socket_role); + descriptor->m_inode = m_inode.copy_ref(); } ASSERT(descriptor); descriptor->m_current_offset = m_current_offset; @@ -80,17 +72,10 @@ Retained<FileDescriptor> FileDescriptor::clone() return *descriptor; } -bool addition_would_overflow(off_t a, off_t b) -{ - ASSERT(a > 0); - uint64_t ua = a; - return (ua + b) > OFF_T_MAX; -} - KResult FileDescriptor::fstat(stat& buffer) { ASSERT(!is_fifo()); - if (!m_inode && !m_file) + if (!m_inode) return KResult(-EBADF); auto metadata = this->metadata(); @@ -122,12 +107,9 @@ KResult FileDescriptor::fchmod(mode_t mode) off_t FileDescriptor::seek(off_t offset, int whence) { - ASSERT(!is_fifo()); - if (!m_inode && !m_file) - return -EBADF; + if (!m_file->is_seekable()) + return -EINVAL; - // FIXME: The file type should be cached on the vnode. - // It's silly that we have to do a full metadata lookup here. auto metadata = this->metadata(); if (!metadata.is_valid()) return -EIO; @@ -135,86 +117,60 @@ off_t FileDescriptor::seek(off_t offset, int whence) if (metadata.is_socket() || metadata.is_fifo()) return -ESPIPE; - off_t newOffset; + off_t new_offset; switch (whence) { case SEEK_SET: - newOffset = offset; + new_offset = offset; break; case SEEK_CUR: - newOffset = m_current_offset + offset; + new_offset = m_current_offset + offset; break; case SEEK_END: - newOffset = metadata.size; + new_offset = metadata.size; break; default: return -EINVAL; } - if (newOffset < 0) + if (new_offset < 0) return -EINVAL; // FIXME: Return -EINVAL if attempting to seek past the end of a seekable device. - m_current_offset = newOffset; + m_current_offset = new_offset; return m_current_offset; } ssize_t FileDescriptor::read(byte* buffer, ssize_t count) { - if (m_file) { - int nread = m_file->read(*this, buffer, count); - if (!m_file->is_seekable()) - m_current_offset += nread; - return nread; - } - ASSERT(inode()); - ssize_t nread = inode()->read_bytes(m_current_offset, count, buffer, this); - m_current_offset += nread; + int nread = m_file->read(*this, buffer, count); + if (m_file->is_seekable()) + m_current_offset += nread; return nread; } ssize_t FileDescriptor::write(const byte* data, ssize_t size) { - if (m_file) { - int nwritten = m_file->write(*this, data, size); - if (m_file->is_seekable()) - m_current_offset += nwritten; - return nwritten; - } - ASSERT(m_inode); - ssize_t nwritten = m_inode->write_bytes(m_current_offset, size, data, this); - m_current_offset += nwritten; + int nwritten = m_file->write(*this, data, size); + if (m_file->is_seekable()) + m_current_offset += nwritten; return nwritten; } bool FileDescriptor::can_write() { - if (m_file) - return m_file->can_write(*this); - return true; + return m_file->can_write(*this); } bool FileDescriptor::can_read() { - if (m_file) - return m_file->can_read(*this); - return true; + return m_file->can_read(*this); } ByteBuffer FileDescriptor::read_entire_file() { // HACK ALERT: (This entire function) - - ASSERT(!is_fifo()); - - if (m_file) { - auto buffer = ByteBuffer::create_uninitialized(1024); - ssize_t nread = m_file->read(*this, buffer.pointer(), buffer.size()); - ASSERT(nread >= 0); - buffer.trim(nread); - return buffer; - } - + ASSERT(m_file->is_inode()); ASSERT(m_inode); return m_inode->read_entire(this); } @@ -255,12 +211,12 @@ ssize_t FileDescriptor::get_dir_entries(byte* buffer, ssize_t size) bool FileDescriptor::is_device() const { - return m_file && m_file->is_device(); + return m_file->is_device(); } bool FileDescriptor::is_tty() const { - return m_file && m_file->is_tty(); + return m_file->is_tty(); } const TTY* FileDescriptor::tty() const @@ -279,7 +235,7 @@ TTY* FileDescriptor::tty() bool FileDescriptor::is_master_pty() const { - return m_file && m_file->is_master_pty(); + return m_file->is_master_pty(); } const MasterPTY* FileDescriptor::master_pty() const @@ -301,17 +257,9 @@ int FileDescriptor::close() return 0; } -bool FileDescriptor::is_fsfile() const -{ - return !is_tty() && !is_fifo() && !is_device() && !is_socket() && !is_shared_memory(); -} - KResultOr<String> FileDescriptor::absolute_path() { - if (m_file) - return m_file->absolute_path(*this); - ASSERT(m_inode); - return VFS::the().absolute_path(*m_inode); + return m_file->absolute_path(*this); } InodeMetadata FileDescriptor::metadata() const @@ -323,40 +271,17 @@ InodeMetadata FileDescriptor::metadata() const KResultOr<Region*> FileDescriptor::mmap(Process& process, LinearAddress laddr, size_t offset, size_t size, int prot) { - if (m_file) - return m_file->mmap(process, laddr, offset, size, prot); - - if (!is_fsfile()) - return KResult(-ENODEV); - - ASSERT(m_inode); - // FIXME: If PROT_EXEC, check that the underlying file system isn't mounted noexec. - String region_name; -#if 0 - // FIXME: I would like to do this, but it would instantiate all the damn inodes. - region_name = absolute_path(); -#else - region_name = "Memory-mapped file"; -#endif - InterruptDisabler disabler; - auto* region = process.allocate_file_backed_region(laddr, size, inode(), move(region_name), prot & PROT_READ, prot & PROT_WRITE); - if (!region) - return KResult(-ENOMEM); - return region; + return m_file->mmap(process, laddr, offset, size, prot); } KResult FileDescriptor::truncate(off_t length) { - if (is_file()) { - return m_inode->truncate(length); - } - ASSERT(is_shared_memory()); - return shared_memory()->truncate(length); + return m_file->truncate(length); } bool FileDescriptor::is_shared_memory() const { - return m_file && m_file->is_shared_memory(); + return m_file->is_shared_memory(); } SharedMemory* FileDescriptor::shared_memory() @@ -375,7 +300,7 @@ const SharedMemory* FileDescriptor::shared_memory() const bool FileDescriptor::is_fifo() const { - return m_file && m_file->is_fifo(); + return m_file->is_fifo(); } FIFO* FileDescriptor::fifo() @@ -387,7 +312,7 @@ FIFO* FileDescriptor::fifo() bool FileDescriptor::is_socket() const { - return m_file && m_file->is_socket(); + return m_file->is_socket(); } Socket* FileDescriptor::socket() diff --git a/Kernel/FileSystem/FileDescriptor.h b/Kernel/FileSystem/FileDescriptor.h index 30ebbce559..60d7cc5679 100644 --- a/Kernel/FileSystem/FileDescriptor.h +++ b/Kernel/FileSystem/FileDescriptor.h @@ -47,10 +47,8 @@ public: bool is_directory() const; - // FIXME: These should go away once everything is a File. - bool is_file() const { return m_file.ptr(); } - File* file() { return m_file.ptr(); } - const File* file() const { return m_file.ptr(); } + File& file() { return *m_file; } + const File& file() const { return *m_file; } bool is_device() const; @@ -85,7 +83,6 @@ public: FIFO::Direction fifo_direction() { return m_fifo_direction; } void set_fifo_direction(Badge<FIFO>, FIFO::Direction direction) { m_fifo_direction = direction; } - bool is_fsfile() const; bool is_shared_memory() const; SharedMemory* shared_memory(); const SharedMemory* shared_memory() const; @@ -99,10 +96,11 @@ public: KResult truncate(off_t); + off_t offset() const { return m_current_offset; } + private: friend class VFS; - FileDescriptor(RetainPtr<File>&&, SocketRole); - explicit FileDescriptor(RetainPtr<Inode>&&); + FileDescriptor(RetainPtr<File>&&, SocketRole = SocketRole::None); FileDescriptor(FIFO&, FIFO::Direction); RetainPtr<Inode> m_inode; diff --git a/Kernel/FileSystem/InodeFile.cpp b/Kernel/FileSystem/InodeFile.cpp new file mode 100644 index 0000000000..c76c1147d7 --- /dev/null +++ b/Kernel/FileSystem/InodeFile.cpp @@ -0,0 +1,55 @@ +#include <Kernel/FileSystem/InodeFile.h> +#include <Kernel/FileSystem/Inode.h> +#include <Kernel/FileSystem/FileDescriptor.h> +#include <Kernel/FileSystem/VirtualFileSystem.h> +#include <Kernel/Process.h> + +InodeFile::InodeFile(Retained<Inode>&& inode) + : m_inode(move(inode)) +{ +} + +InodeFile::~InodeFile() +{ +} + +ssize_t InodeFile::read(FileDescriptor& descriptor, byte* buffer, ssize_t count) +{ + return m_inode->read_bytes(descriptor.offset(), count, buffer, &descriptor); +} + +ssize_t InodeFile::write(FileDescriptor& descriptor, const byte* data, ssize_t count) +{ + return m_inode->write_bytes(descriptor.offset(), count, data, &descriptor); +} + +KResultOr<Region*> InodeFile::mmap(Process& process, LinearAddress preferred_laddr, size_t offset, size_t size, int prot) +{ + ASSERT(offset == 0); + // FIXME: If PROT_EXEC, check that the underlying file system isn't mounted noexec. + String region_name; +#if 0 + // FIXME: I would like to do this, but it would instantiate all the damn inodes. + region_name = absolute_path(); +#else + region_name = "Memory-mapped file"; +#endif + InterruptDisabler disabler; + auto* region = process.allocate_file_backed_region(preferred_laddr, size, inode(), move(region_name), prot & PROT_READ, prot & PROT_WRITE); + if (!region) + return KResult(-ENOMEM); + return region; +} + +String InodeFile::absolute_path(FileDescriptor&) const +{ + auto path_or_error = VFS::the().absolute_path(const_cast<Inode&>(inode())); + if (path_or_error.is_error()) + return { }; + return path_or_error.value(); +} + +KResult InodeFile::truncate(off_t size) +{ + return m_inode->truncate(size); +} diff --git a/Kernel/FileSystem/InodeFile.h b/Kernel/FileSystem/InodeFile.h new file mode 100644 index 0000000000..5c86386005 --- /dev/null +++ b/Kernel/FileSystem/InodeFile.h @@ -0,0 +1,38 @@ +#pragma once + +#include <Kernel/File.h> + +class Inode; + +class InodeFile final : public File { +public: + static Retained<InodeFile> create(Retained<Inode>&& inode) + { + return adopt(*new InodeFile(move(inode))); + } + + virtual ~InodeFile() override; + + const Inode& inode() const { return *m_inode; } + Inode& inode() { return *m_inode; } + + virtual bool can_read(FileDescriptor&) const override { return true; } + virtual bool can_write(FileDescriptor&) const override { return true; } + + virtual ssize_t read(FileDescriptor&, byte*, ssize_t) override; + virtual ssize_t write(FileDescriptor&, const byte*, ssize_t) override; + virtual KResultOr<Region*> mmap(Process&, LinearAddress preferred_laddr, size_t offset, size_t size, int prot) override; + + virtual String absolute_path(FileDescriptor&) const override; + + virtual KResult truncate(off_t) override; + + virtual const char* class_name() const override { return "InodeFile"; } + + virtual bool is_seekable() const override { return true; } + virtual bool is_inode() const override { return true; } + +private: + explicit InodeFile(Retained<Inode>&&); + Retained<Inode> m_inode; +}; |