From dc35c423714b11eaa3270a743b3ecaefe5c272b4 Mon Sep 17 00:00:00 2001 From: apio Date: Tue, 1 Aug 2023 17:20:28 +0200 Subject: [PATCH] kernel/VFS: Rework the metadata system so that there is a single metadata struct --- kernel/src/fs/InitRD.cpp | 12 +- kernel/src/fs/Mount.h | 46 +---- kernel/src/fs/Pipe.cpp | 10 +- kernel/src/fs/Pipe.h | 34 +--- kernel/src/fs/VFS.cpp | 40 ++-- kernel/src/fs/VFS.h | 78 ++++---- kernel/src/fs/devices/DeviceRegistry.cpp | 3 +- kernel/src/fs/ext2/FileSystem.cpp | 9 +- kernel/src/fs/ext2/FileSystem.h | 6 +- kernel/src/fs/ext2/Inode.cpp | 15 +- kernel/src/fs/ext2/Inode.h | 38 +--- kernel/src/fs/tmpfs/FileSystem.cpp | 12 +- kernel/src/fs/tmpfs/FileSystem.h | 6 +- kernel/src/fs/tmpfs/Inode.cpp | 17 +- kernel/src/fs/tmpfs/Inode.h | 224 +++-------------------- kernel/src/net/Socket.h | 56 +----- kernel/src/net/UnixSocket.cpp | 9 +- kernel/src/net/UnixSocket.h | 2 +- kernel/src/sys/exec.cpp | 4 +- kernel/src/sys/file.cpp | 4 +- kernel/src/sys/getdents.cpp | 2 +- kernel/src/sys/id.cpp | 15 +- kernel/src/sys/link.cpp | 9 +- kernel/src/sys/mkdir.cpp | 9 +- kernel/src/sys/mount.cpp | 2 +- kernel/src/sys/open.cpp | 17 +- kernel/src/sys/socket.cpp | 2 +- kernel/src/sys/stat.cpp | 16 +- 28 files changed, 203 insertions(+), 494 deletions(-) diff --git a/kernel/src/fs/InitRD.cpp b/kernel/src/fs/InitRD.cpp index 5c727574..a083198b 100644 --- a/kernel/src/fs/InitRD.cpp +++ b/kernel/src/fs/InitRD.cpp @@ -18,17 +18,15 @@ void InitRD::initialize() g_initrd.initialize((void*)virtual_initrd_address, bootboot.initrd_size); } -static Result vfs_create_dir_if_not_exists(const char* path, mode_t mode, uid_t uid, gid_t gid) +static Result vfs_create_dir_if_not_exists(const char* path, mode_t mode) { - auto rc = VFS::create_directory(path, Credentials {}); + auto rc = VFS::create_directory(path, mode & (mode_t)~S_IFMT, Credentials {}); if (rc.has_error()) { if (rc.error() == EEXIST) return {}; return rc.release_error(); } auto dir = rc.value(); - dir->chmod(mode & (mode_t)~S_IFMT); - dir->chown(uid, gid); return {}; } @@ -39,14 +37,12 @@ Result InitRD::populate_vfs() { if (entry.type == TarStream::EntryType::RegularFile) { - auto file = TRY(VFS::create_file(entry.name.chars(), Credentials {})); + auto file = TRY(VFS::create_file(entry.name.chars(), entry.mode & (mode_t)~S_IFMT, Credentials {})); file->write(entry.data(), 0, entry.size); - file->chmod(entry.mode & (mode_t)~S_IFMT); - file->chown(entry.uid, entry.gid); } else if (entry.type == TarStream::EntryType::Directory) { - TRY(vfs_create_dir_if_not_exists(entry.name.chars(), entry.mode, entry.uid, entry.gid)); + TRY(vfs_create_dir_if_not_exists(entry.name.chars(), entry.mode)); } } diff --git a/kernel/src/fs/Mount.h b/kernel/src/fs/Mount.h index bb8ee36d..53c14629 100644 --- a/kernel/src/fs/Mount.h +++ b/kernel/src/fs/Mount.h @@ -42,39 +42,14 @@ class MountInode : public VFS::Inode, public LinkedListNode return false; } - usize size() const override + const VFS::InodeMetadata& metadata() const override { - return 0; + return m_mount_root_inode->metadata(); } - mode_t mode() const override + Result set_metadata(const VFS::InodeMetadata& metadata) override { - return m_mount_root_inode->mode(); - } - - u32 uid() const override - { - return m_mount_root_inode->uid(); - } - - u32 gid() const override - { - return m_mount_root_inode->gid(); - } - - nlink_t nlinks() const override - { - return m_mount_root_inode->nlinks(); - } - - Result chmod(mode_t mode) override - { - return m_mount_root_inode->chmod(mode); - } - - Result chown(u32 uid, u32 gid) override - { - return m_mount_root_inode->chown(uid, gid); + return m_mount_root_inode->set_metadata(metadata); } VFS::FileSystem* fs() const override @@ -82,11 +57,6 @@ class MountInode : public VFS::Inode, public LinkedListNode return m_mountee.ptr(); } - usize inode_number() const override - { - return m_mount_root_inode->inode_number(); - } - VFS::InodeType type() const override { return VFS::InodeType::Directory; @@ -122,14 +92,14 @@ class MountInode : public VFS::Inode, public LinkedListNode return m_mount_root_inode->remove_entry(name); } - Result> create_file(const char* name) override + Result> create_file(const char* name, mode_t mode) override { - return m_mount_root_inode->create_file(name); + return m_mount_root_inode->create_file(name, mode); } - Result> create_subdirectory(const char* name) override + Result> create_subdirectory(const char* name, mode_t mode) override { - return m_mount_root_inode->create_subdirectory(name); + return m_mount_root_inode->create_subdirectory(name, mode); } Result add_entry(SharedPtr inode, const char* name) override diff --git a/kernel/src/fs/Pipe.cpp b/kernel/src/fs/Pipe.cpp index edbb180f..d55707de 100644 --- a/kernel/src/fs/Pipe.cpp +++ b/kernel/src/fs/Pipe.cpp @@ -14,8 +14,14 @@ Result Pipe::create(SharedPtr& rpipe, SharedPtr& w pipe->m_reader = reader.ptr(); writer->m_pipe = reader->m_pipe = pipe; - writer->chown(auth.euid, auth.egid); - reader->chown(auth.euid, auth.egid); + writer->m_metadata.inum = 0; + writer->m_metadata.uid = auth.euid; + writer->m_metadata.gid = auth.egid; + writer->m_metadata.mode = 0200; + reader->m_metadata.inum = 0; + reader->m_metadata.uid = auth.euid; + reader->m_metadata.gid = auth.egid; + reader->m_metadata.mode = 0400; rpipe = reader; wpipe = writer; diff --git a/kernel/src/fs/Pipe.h b/kernel/src/fs/Pipe.h index 76bc0d73..f4a1b740 100644 --- a/kernel/src/fs/Pipe.h +++ b/kernel/src/fs/Pipe.h @@ -45,9 +45,10 @@ class PipeInodeBase : public VFS::FileInode return m_pipe->will_block_if_read(); } - usize size() const override + const VFS::InodeMetadata& metadata() const override { - return m_pipe->m_data_buffer.size(); + m_metadata.size = m_pipe->m_data_buffer.size(); + return m_metadata; } void did_link() override @@ -58,23 +59,6 @@ class PipeInodeBase : public VFS::FileInode { } - Result chmod(mode_t) override - { - return err(ENOTSUP); - } - - Result chown(u32 uid, u32 gid) override - { - m_uid = uid; - m_gid = gid; - return {}; - } - - usize inode_number() const override - { - return 0; - } - VFS::FileSystem* fs() const override { return nullptr; @@ -86,8 +70,6 @@ class PipeInodeBase : public VFS::FileInode protected: SharedPtr m_pipe; - u32 m_uid { 0 }; - u32 m_gid { 0 }; }; class PipeWriter : public PipeInodeBase @@ -104,11 +86,6 @@ class PipeWriter : public PipeInodeBase return m_pipe->write(buf, offset, length); } - mode_t mode() const override - { - return 0200; - } - ~PipeWriter(); friend class Pipe; @@ -128,11 +105,6 @@ class PipeReader : public PipeInodeBase check(false); } - mode_t mode() const override - { - return 0400; - } - ~PipeReader(); friend class Pipe; diff --git a/kernel/src/fs/VFS.cpp b/kernel/src/fs/VFS.cpp index 38cc3e37..fd5c67ae 100644 --- a/kernel/src/fs/VFS.cpp +++ b/kernel/src/fs/VFS.cpp @@ -69,7 +69,8 @@ namespace VFS return resolve_path_impl(path, auth, current_inode, follow_last_symlink, symlinks_followed); } - Result> create_directory(const char* path, Credentials auth, SharedPtr working_directory) + Result> create_directory(const char* path, mode_t mode, Credentials auth, + SharedPtr working_directory) { auto parent_path = TRY(PathParser::dirname(path)); @@ -81,10 +82,11 @@ namespace VFS TRY(validate_filename(child_name.view())); - return parent_inode->create_subdirectory(child_name.chars()); + return parent_inode->create_subdirectory(child_name.chars(), mode); } - Result> create_file(const char* path, Credentials auth, SharedPtr working_directory) + Result> create_file(const char* path, mode_t mode, Credentials auth, + SharedPtr working_directory) { auto parent_path = TRY(PathParser::dirname(path)); @@ -96,7 +98,7 @@ namespace VFS TRY(validate_filename(child_name.view())); - return parent_inode->create_file(child_name.chars()); + return parent_inode->create_file(child_name.chars(), mode); } Result validate_filename(StringView name) @@ -135,45 +137,51 @@ namespace VFS { if (auth.euid == 0) return true; - if (inode->uid() == auth.euid) { return inode->mode() & S_IXUSR; } - if (inode->gid() == auth.egid) { return inode->mode() & S_IXGRP; } + const auto& metadata = inode->metadata(); - return inode->mode() & S_IXOTH; + if (metadata.uid == auth.euid) { return metadata.mode & S_IXUSR; } + if (metadata.gid == auth.egid) { return metadata.mode & S_IXGRP; } + + return metadata.mode & S_IXOTH; } bool can_write(SharedPtr inode, Credentials auth) { if (auth.euid == 0) return true; - if (inode->uid() == auth.euid) { return inode->mode() & S_IWUSR; } - if (inode->gid() == auth.egid) { return inode->mode() & S_IWGRP; } + const auto& metadata = inode->metadata(); - return inode->mode() & S_IWOTH; + if (metadata.uid == auth.euid) { return metadata.mode & S_IWUSR; } + if (metadata.gid == auth.egid) { return metadata.mode & S_IWGRP; } + + return metadata.mode & S_IWOTH; } bool can_read(SharedPtr inode, Credentials auth) { if (auth.euid == 0) return true; - if (inode->uid() == auth.euid) { return inode->mode() & S_IRUSR; } - if (inode->gid() == auth.egid) { return inode->mode() & S_IRGRP; } + const auto& metadata = inode->metadata(); - return inode->mode() & S_IROTH; + if (metadata.uid == auth.euid) { return metadata.mode & S_IRUSR; } + if (metadata.gid == auth.egid) { return metadata.mode & S_IRGRP; } + + return metadata.mode & S_IROTH; } bool is_setuid(SharedPtr inode) { - return inode->mode() & S_ISUID; + return inode->metadata().mode & S_ISUID; } bool is_setgid(SharedPtr inode) { - return inode->mode() & S_ISGID; + return inode->metadata().mode & S_ISGID; } bool is_sticky(SharedPtr inode) { - return inode->mode() & S_ISVTX; + return inode->metadata().mode & S_ISVTX; } bool is_seekable(SharedPtr inode) diff --git a/kernel/src/fs/VFS.h b/kernel/src/fs/VFS.h index e7dff461..a3732a66 100644 --- a/kernel/src/fs/VFS.h +++ b/kernel/src/fs/VFS.h @@ -1,5 +1,7 @@ #pragma once +#include "arch/Timer.h" #include +#include #include #include #include @@ -20,6 +22,21 @@ namespace VFS Socket, }; + struct InodeMetadata + { + ino_t inum; + size_t size { 0 }; + mode_t mode; + nlink_t nlinks { 1 }; + uid_t uid { 0 }; + gid_t gid { 0 }; + dev_t devid { 0 }; + + struct timespec atime; + struct timespec mtime; + struct timespec ctime; + }; + class Inode; class FileSystem : public Shareable @@ -27,11 +44,11 @@ namespace VFS public: virtual SharedPtr root_inode() const = 0; - virtual Result> create_file_inode() = 0; + virtual Result> create_file_inode(mode_t mode) = 0; - virtual Result> create_dir_inode(SharedPtr parent) = 0; + virtual Result> create_dir_inode(SharedPtr parent, mode_t mode) = 0; - virtual Result> create_device_inode(u32 major, u32 minor) = 0; + virtual Result> create_device_inode(u32 major, u32 minor, mode_t mode) = 0; virtual Result> create_symlink_inode(StringView link) = 0; @@ -101,9 +118,9 @@ namespace VFS virtual Option get(usize index) const = 0; - virtual Result> create_file(const char* name) = 0; + virtual Result> create_file(const char* name, mode_t mode) = 0; - virtual Result> create_subdirectory(const char* name) = 0; + virtual Result> create_subdirectory(const char* name, mode_t mode) = 0; virtual Result add_entry(SharedPtr inode, const char* name) = 0; @@ -128,29 +145,16 @@ namespace VFS return StringView {}; } - virtual dev_t device_id() const + virtual const InodeMetadata& metadata() const { - return luna_dev_makedev(0, 0); + return m_metadata; } - // Metadata accessors - virtual usize size() const = 0; - - virtual mode_t mode() const = 0; - - virtual nlink_t nlinks() const + virtual Result set_metadata(const InodeMetadata& metadata) { - return 1; - } - - virtual u32 uid() const - { - return 0; - } - - virtual u32 gid() const - { - return 0; + m_metadata = metadata; + m_metadata.ctime = *Timer::realtime_clock(); + return {}; } virtual bool is_mountpoint() const @@ -161,11 +165,6 @@ namespace VFS virtual void did_link() = 0; virtual void did_unlink() = 0; - // Metadata changers - virtual Result chmod(mode_t mode) = 0; - - virtual Result chown(u32 uid, u32 gid) = 0; - // Generic VFS-related methods virtual FileSystem* fs() const = 0; @@ -173,8 +172,6 @@ namespace VFS virtual InodeType type() const = 0; - virtual usize inode_number() const = 0; - virtual void add_handle() { auto* f = fs(); @@ -186,9 +183,12 @@ namespace VFS auto* f = fs(); if (f) f->remove_handle(); } + + protected: + mutable InodeMetadata m_metadata; }; - class FileInode : Inode + class FileInode : public Inode { public: Result> find(const char*) const override @@ -201,12 +201,12 @@ namespace VFS return {}; } - Result> create_file(const char*) override + Result> create_file(const char*, mode_t) override { return err(ENOTDIR); } - Result> create_subdirectory(const char*) override + Result> create_subdirectory(const char*, mode_t) override { return err(ENOTDIR); } @@ -244,7 +244,7 @@ namespace VFS virtual ~FileInode() = default; }; - class DeviceInode : Inode + class DeviceInode : public Inode { public: Result> find(const char*) const override @@ -257,12 +257,12 @@ namespace VFS return {}; } - Result> create_file(const char*) override + Result> create_file(const char*, mode_t) override { return err(ENOTDIR); } - Result> create_subdirectory(const char*) override + Result> create_subdirectory(const char*, mode_t) override { return err(ENOTDIR); } @@ -299,10 +299,10 @@ namespace VFS SharedPtr working_directory = {}, bool follow_last_symlink = true); - Result> create_directory(const char* path, Credentials auth, + Result> create_directory(const char* path, mode_t mode, Credentials auth, SharedPtr working_directory = {}); - Result> create_file(const char* path, Credentials auth, + Result> create_file(const char* path, mode_t mode, Credentials auth, SharedPtr working_directory = {}); Result validate_filename(StringView name); diff --git a/kernel/src/fs/devices/DeviceRegistry.cpp b/kernel/src/fs/devices/DeviceRegistry.cpp index fd73a633..7ea54229 100644 --- a/kernel/src/fs/devices/DeviceRegistry.cpp +++ b/kernel/src/fs/devices/DeviceRegistry.cpp @@ -36,8 +36,7 @@ namespace DeviceRegistry Result create_special_device_inode(SharedPtr fs, const DeviceDescriptor& descriptor) { - auto inode = TRY(fs->create_device_inode(descriptor.major, descriptor.minor)); - inode->chmod(descriptor.mode); + auto inode = TRY(fs->create_device_inode(descriptor.major, descriptor.minor, descriptor.mode)); TRY(fs->root_inode()->add_entry(inode, descriptor.name)); return {}; diff --git a/kernel/src/fs/ext2/FileSystem.cpp b/kernel/src/fs/ext2/FileSystem.cpp index 9735f3a9..6d8b936a 100644 --- a/kernel/src/fs/ext2/FileSystem.cpp +++ b/kernel/src/fs/ext2/FileSystem.cpp @@ -49,7 +49,14 @@ namespace Ext2 auto inode = TRY(adopt_shared_if_nonnull(new (std::nothrow) Ext2::Inode({}, this))); TRY(m_host_device->read((u8*)&inode->m_raw_inode, inode_address, INODE_SIZE)); inode->m_type = vfs_type_from_ext2_type(inode->m_raw_inode.mode); - inode->m_inum = inum; + inode->m_metadata.inum = inum; + inode->m_metadata.size = (m_uses_extended_size && (inode->m_type == VFS::InodeType::RegularFile)) + ? ((u64)inode->m_raw_inode.size_high << 32) | (u64)inode->m_raw_inode.size_low + : inode->m_raw_inode.size_low; + inode->m_metadata.mode = inode->m_raw_inode.mode & 07777; + inode->m_metadata.nlinks = inode->m_raw_inode.nlinks; + inode->m_metadata.uid = inode->m_raw_inode.uid; + inode->m_metadata.gid = inode->m_raw_inode.gid; #ifdef EXT2_DEBUG kdbgln("ext2: Read inode %lu with mode %#x (%#x + %#o), size %lu", inum, inode->m_raw_inode.mode, diff --git a/kernel/src/fs/ext2/FileSystem.h b/kernel/src/fs/ext2/FileSystem.h index 59fee651..857a7ade 100644 --- a/kernel/src/fs/ext2/FileSystem.h +++ b/kernel/src/fs/ext2/FileSystem.h @@ -127,17 +127,17 @@ namespace Ext2 return m_root_inode; } - Result> create_file_inode() override + Result> create_file_inode(mode_t) override { return err(EROFS); } - Result> create_dir_inode(SharedPtr) override + Result> create_dir_inode(SharedPtr, mode_t) override { return err(EROFS); } - Result> create_device_inode(u32, u32) override + Result> create_device_inode(u32, u32, mode_t) override { return err(EROFS); } diff --git a/kernel/src/fs/ext2/Inode.cpp b/kernel/src/fs/ext2/Inode.cpp index 309a4278..261adcab 100644 --- a/kernel/src/fs/ext2/Inode.cpp +++ b/kernel/src/fs/ext2/Inode.cpp @@ -7,19 +7,12 @@ namespace Ext2 { } - usize Inode::size() const - { - return (m_fs->m_uses_extended_size && (m_type == VFS::InodeType::RegularFile)) - ? ((u64)m_raw_inode.size_high << 32) | (u64)m_raw_inode.size_low - : m_raw_inode.size_low; - } - Result Inode::read(u8* buf, usize offset, usize length) const { if (length == 0) return 0; - if (offset > size()) return 0; - if (offset + length > size()) length = size() - offset; + if (offset > m_metadata.size) return 0; + if (offset + length > m_metadata.size) length = m_metadata.size - offset; const usize block_size = m_fs->m_block_size; @@ -95,7 +88,7 @@ namespace Ext2 { check(m_type == VFS::InodeType::Directory); - const usize inode_size = size(); + const usize inode_size = m_metadata.size; const usize block_size = m_fs->m_block_size; u8* const buf = TRY(make_array(block_size)); @@ -184,7 +177,7 @@ namespace Ext2 if (!m_link.is_empty()) return m_link.view(); - const usize length = size(); + const usize length = m_metadata.size; if (length < 60) { diff --git a/kernel/src/fs/ext2/Inode.h b/kernel/src/fs/ext2/Inode.h index 5c9c0c7c..ee88e481 100644 --- a/kernel/src/fs/ext2/Inode.h +++ b/kernel/src/fs/ext2/Inode.h @@ -21,33 +21,6 @@ namespace Ext2 return m_type; } - usize size() const override; - - mode_t mode() const override - { - return m_raw_inode.mode & 07777; - } - - nlink_t nlinks() const override - { - return m_raw_inode.nlinks; - } - - u32 uid() const override - { - return m_raw_inode.uid; - } - - u32 gid() const override - { - return m_raw_inode.gid; - } - - usize inode_number() const override - { - return m_inum; - } - VFS::FileSystem* fs() const override { return m_fs; @@ -61,12 +34,7 @@ namespace Ext2 { } - Result chmod(mode_t) override - { - return err(EROFS); - } - - Result chown(u32, u32) override + Result set_metadata(const VFS::InodeMetadata&) override { return err(EROFS); } @@ -87,14 +55,14 @@ namespace Ext2 Option get(usize) const override; - Result> create_file(const char*) override + Result> create_file(const char*, mode_t) override { if (m_type != VFS::InodeType::Directory) return err(ENOTDIR); return err(EROFS); } - Result> create_subdirectory(const char*) override + Result> create_subdirectory(const char*, mode_t) override { if (m_type != VFS::InodeType::Directory) return err(ENOTDIR); diff --git a/kernel/src/fs/tmpfs/FileSystem.cpp b/kernel/src/fs/tmpfs/FileSystem.cpp index 71d0488c..6dd2a395 100644 --- a/kernel/src/fs/tmpfs/FileSystem.cpp +++ b/kernel/src/fs/tmpfs/FileSystem.cpp @@ -10,8 +10,7 @@ namespace TmpFS Result> FileSystem::create() { SharedPtr fs = TRY(adopt_shared_if_nonnull(new (std::nothrow) FileSystem())); - SharedPtr root = TRY(fs->create_dir_inode({})); - root->chmod(0755); + SharedPtr root = TRY(fs->create_dir_inode({}, 0755)); fs->set_root(root); return (SharedPtr)fs; } @@ -21,11 +20,12 @@ namespace TmpFS return m_next_inode_number++; } - Result> FileSystem::create_file_inode() + Result> FileSystem::create_file_inode(mode_t mode) { SharedPtr inode = TRY(make_shared()); inode->set_fs(*this, {}); inode->set_inode_number(m_next_inode_number++, {}); + inode->m_metadata.mode = mode; return (SharedPtr)inode; } @@ -38,7 +38,7 @@ namespace TmpFS return (SharedPtr)inode; } - Result> FileSystem::create_dir_inode(SharedPtr parent) + Result> FileSystem::create_dir_inode(SharedPtr parent, mode_t mode) { SharedPtr inode = TRY(make_shared()); @@ -48,11 +48,12 @@ namespace TmpFS inode->set_self(inode, {}); inode->set_fs(*this, {}); inode->set_inode_number(m_next_inode_number++, {}); + inode->m_metadata.mode = mode; return (SharedPtr)inode; } - Result> FileSystem::create_device_inode(u32 major, u32 minor) + Result> FileSystem::create_device_inode(u32 major, u32 minor, mode_t mode) { SharedPtr device = TRY(DeviceRegistry::fetch_special_device(major, minor)); @@ -63,6 +64,7 @@ namespace TmpFS // FIXME: This should be queried from Device directly, but Device doesn't have an API to store and retrieve its // device ID atm. inode->set_device_id(luna_dev_makedev(major, minor), {}); + inode->m_metadata.mode = mode; return (SharedPtr)inode; } diff --git a/kernel/src/fs/tmpfs/FileSystem.h b/kernel/src/fs/tmpfs/FileSystem.h index 2d598a9c..46eb3b94 100644 --- a/kernel/src/fs/tmpfs/FileSystem.h +++ b/kernel/src/fs/tmpfs/FileSystem.h @@ -13,9 +13,9 @@ namespace TmpFS return m_root_inode; } - Result> create_file_inode() override; - Result> create_dir_inode(SharedPtr parent) override; - Result> create_device_inode(u32 major, u32 minor) override; + Result> create_file_inode(mode_t mode) override; + Result> create_dir_inode(SharedPtr parent, mode_t mode) override; + Result> create_device_inode(u32 major, u32 minor, mode_t mode) override; Result> create_symlink_inode(StringView link) override; Result allocate_inode_number() override; diff --git a/kernel/src/fs/tmpfs/Inode.cpp b/kernel/src/fs/tmpfs/Inode.cpp index 221dfb99..a92ec3cb 100644 --- a/kernel/src/fs/tmpfs/Inode.cpp +++ b/kernel/src/fs/tmpfs/Inode.cpp @@ -62,18 +62,18 @@ namespace TmpFS return {}; } - Result> DirInode::create_file(const char* name) + Result> DirInode::create_file(const char* name, mode_t mode) { - auto inode = TRY(m_fs->create_file_inode()); + auto inode = TRY(m_fs->create_file_inode(mode)); TRY(add_entry(inode, name)); return inode; } - Result> DirInode::create_subdirectory(const char* name) + Result> DirInode::create_subdirectory(const char* name, mode_t mode) { - auto inode = TRY(m_fs->create_dir_inode(m_self)); + auto inode = TRY(m_fs->create_dir_inode(m_self, mode)); TRY(add_entry(inode, name)); @@ -110,6 +110,8 @@ namespace TmpFS u8* slice = TRY(m_data_buffer.slice(offset, length)); memcpy(slice, buf, length); + m_metadata.size = m_data_buffer.size(); + return length; } @@ -121,11 +123,8 @@ namespace TmpFS if (size > old_size) memset(m_data_buffer.data() + old_size, 0, size - old_size); + m_metadata.size = m_data_buffer.size(); + return {}; } - - usize FileInode::size() const - { - return m_data_buffer.size(); - } } diff --git a/kernel/src/fs/tmpfs/Inode.h b/kernel/src/fs/tmpfs/Inode.h index cdf87f70..c89b2b78 100644 --- a/kernel/src/fs/tmpfs/Inode.h +++ b/kernel/src/fs/tmpfs/Inode.h @@ -20,68 +20,27 @@ namespace TmpFS void set_inode_number(usize inum, Badge) { - m_inode_number = inum; + m_metadata.inum = inum; } VFS::FileSystem* fs() const override { return m_fs; } - - usize inode_number() const override - { - return m_inode_number; - } - Result read(u8*, usize, usize) const override; Result write(const u8*, usize, usize) override; Result truncate(usize size) override; - usize size() const override; - - mode_t mode() const override - { - return m_mode; - } - - u32 uid() const override - { - return m_uid; - } - - u32 gid() const override - { - return m_gid; - } - - nlink_t nlinks() const override - { - return (nlink_t)m_nlinks; - } - - Result chmod(mode_t mode) override - { - m_mode = mode; - return {}; - } - - Result chown(u32 uid, u32 gid) override - { - m_uid = uid; - m_gid = gid; - return {}; - } - void did_link() override { - m_nlinks++; + m_metadata.nlinks++; } void did_unlink() override { - m_nlinks--; + m_metadata.nlinks--; } virtual ~FileInode() = default; @@ -89,11 +48,8 @@ namespace TmpFS private: VFS::FileSystem* m_fs; Buffer m_data_buffer; - usize m_inode_number; - mode_t m_mode; - u32 m_uid { 0 }; - u32 m_gid { 0 }; - u32 m_nlinks { 0 }; + + friend class FileSystem; }; class SymlinkInode : public VFS::FileInode @@ -113,7 +69,7 @@ namespace TmpFS void set_inode_number(usize inum, Badge) { - m_inode_number = inum; + m_metadata.inum = inum; } Result set_link(StringView link, Badge) @@ -127,11 +83,6 @@ namespace TmpFS return m_fs; } - usize inode_number() const override - { - return m_inode_number; - } - Result read(u8*, usize, usize) const override { return err(ENOTSUP); @@ -147,51 +98,14 @@ namespace TmpFS return err(ENOTSUP); } - usize size() const override - { - return m_link.length(); - } - - mode_t mode() const override - { - return 0777; - } - - u32 uid() const override - { - return m_uid; - } - - u32 gid() const override - { - return m_gid; - } - - nlink_t nlinks() const override - { - return (nlink_t)m_nlinks; - } - - Result chmod(mode_t) override - { - return {}; - } - - Result chown(u32 uid, u32 gid) override - { - m_uid = uid; - m_gid = gid; - return {}; - } - void did_link() override { - m_nlinks++; + m_metadata.nlinks++; } void did_unlink() override { - m_nlinks--; + m_metadata.nlinks--; } Result readlink() override @@ -204,10 +118,8 @@ namespace TmpFS private: VFS::FileSystem* m_fs; String m_link; - usize m_inode_number; - u32 m_uid { 0 }; - u32 m_gid { 0 }; - u32 m_nlinks { 0 }; + + friend class FileSystem; }; class DeviceInode : public VFS::DeviceInode @@ -227,7 +139,7 @@ namespace TmpFS void set_inode_number(usize inum, Badge) { - m_inode_number = inum; + m_metadata.inum = inum; } void set_device(SharedPtr device, Badge) @@ -237,7 +149,7 @@ namespace TmpFS void set_device_id(dev_t id, Badge) { - m_device_id = id; + m_metadata.devid = id; } VFS::FileSystem* fs() const override @@ -245,16 +157,6 @@ namespace TmpFS return m_fs; } - dev_t device_id() const override - { - return m_device_id; - } - - usize inode_number() const override - { - return m_inode_number; - } - Result read(u8* buf, usize offset, usize length) const override { return m_device->read(buf, offset, length); @@ -286,52 +188,14 @@ namespace TmpFS return m_device->will_block_if_read(); } - usize size() const override - { - return m_device->size(); - } - - mode_t mode() const override - { - return m_mode; - } - - u32 uid() const override - { - return m_uid; - } - - u32 gid() const override - { - return m_gid; - } - - nlink_t nlinks() const override - { - return (nlink_t)m_nlinks; - } - - Result chmod(mode_t mode) override - { - m_mode = mode; - return {}; - } - - Result chown(u32 uid, u32 gid) override - { - m_uid = uid; - m_gid = gid; - return {}; - } - void did_link() override { - m_nlinks++; + m_metadata.nlinks++; } void did_unlink() override { - m_nlinks--; + m_metadata.nlinks--; } virtual ~DeviceInode() = default; @@ -339,12 +203,8 @@ namespace TmpFS private: VFS::FileSystem* m_fs; SharedPtr m_device; - usize m_inode_number; - mode_t m_mode; - u32 m_uid { 0 }; - u32 m_gid { 0 }; - u32 m_nlinks { 0 }; - dev_t m_device_id { 0 }; + + friend class FileSystem; }; class DirInode : public VFS::Inode @@ -359,7 +219,7 @@ namespace TmpFS void set_inode_number(usize inum, Badge) { - m_inode_number = inum; + m_metadata.inum = inum; } void set_self(SharedPtr self, Badge) @@ -390,49 +250,11 @@ namespace TmpFS return false; } - usize size() const override - { - return 0; - } - - mode_t mode() const override - { - return m_mode; - } - - u32 uid() const override - { - return m_uid; - } - - u32 gid() const override - { - return m_gid; - } - - Result chmod(mode_t mode) override - { - m_mode = mode; - return {}; - } - - Result chown(u32 uid, u32 gid) override - { - m_uid = uid; - m_gid = gid; - return {}; - } - VFS::FileSystem* fs() const override { return m_fs; } - usize inode_number() const override - { - return m_inode_number; - } - VFS::InodeType type() const override { return VFS::InodeType::Directory; @@ -455,8 +277,8 @@ namespace TmpFS Result remove_entry(const char* name) override; - Result> create_file(const char* name) override; - Result> create_subdirectory(const char* name) override; + Result> create_file(const char* name, mode_t mode) override; + Result> create_subdirectory(const char* name, mode_t mode) override; Result add_entry(SharedPtr inode, const char* name); Result replace_entry(SharedPtr inode, const char* name); @@ -465,13 +287,9 @@ namespace TmpFS private: VFS::FileSystem* m_fs; - usize m_inode_number; - mode_t m_mode; - u32 m_uid { 0 }; - u32 m_gid { 0 }; - SharedPtr m_self; - Vector m_entries; + + friend class FileSystem; }; } diff --git a/kernel/src/net/Socket.h b/kernel/src/net/Socket.h index fa7eb101..1ac16c92 100644 --- a/kernel/src/net/Socket.h +++ b/kernel/src/net/Socket.h @@ -21,7 +21,7 @@ class Socket : public VFS::FileInode void set_inode_number(usize inum) { - m_inode_number = inum; + m_metadata.inum = inum; } VFS::FileSystem* fs() const override @@ -29,11 +29,6 @@ class Socket : public VFS::FileInode return m_fs; } - usize inode_number() const override - { - return m_inode_number; - } - Result read(u8* buf, usize, usize length) const override { return recv(buf, length, 0); @@ -48,7 +43,7 @@ class Socket : public VFS::FileInode virtual Result recv(u8*, usize, int) const = 0; - virtual Result bind(SharedPtr, struct sockaddr*, socklen_t) = 0; + virtual Result bind(struct sockaddr*, socklen_t) = 0; virtual Result connect(Registers*, int, struct sockaddr*, socklen_t) = 0; virtual Result> accept(Registers*, int, struct sockaddr**, socklen_t*) = 0; @@ -60,61 +55,18 @@ class Socket : public VFS::FileInode return err(EINVAL); } - usize size() const override - { - return 0; - } - - mode_t mode() const override - { - return m_mode; - } - - u32 uid() const override - { - return m_uid; - } - - u32 gid() const override - { - return m_gid; - } - - nlink_t nlinks() const override - { - return (nlink_t)m_nlinks; - } - - Result chmod(mode_t mode) override - { - m_mode = mode; - return {}; - } - - Result chown(u32 uid, u32 gid) override - { - m_uid = uid; - m_gid = gid; - return {}; - } - void did_link() override { - m_nlinks++; + m_metadata.nlinks++; } void did_unlink() override { - m_nlinks--; + m_metadata.nlinks--; } virtual ~Socket() = default; protected: VFS::FileSystem* m_fs { nullptr }; - usize m_inode_number { 0 }; - mode_t m_mode; - u32 m_uid { 0 }; - u32 m_gid { 0 }; - u32 m_nlinks { 0 }; }; diff --git a/kernel/src/net/UnixSocket.cpp b/kernel/src/net/UnixSocket.cpp index 8530c3d3..7ba013a6 100644 --- a/kernel/src/net/UnixSocket.cpp +++ b/kernel/src/net/UnixSocket.cpp @@ -71,7 +71,7 @@ static Result bind_socket_to_fs(const char* path, Credentials auth, Shared return parent_inode->add_entry(socket, child_name.chars()); } -Result UnixSocket::bind(SharedPtr socket, struct sockaddr* addr, socklen_t addrlen) +Result UnixSocket::bind(struct sockaddr* addr, socklen_t addrlen) { if (!addr) return err(EDESTADDRREQ); if (addr->sa_family != AF_UNIX) return err(EAFNOSUPPORT); @@ -87,10 +87,11 @@ Result UnixSocket::bind(SharedPtr socket, struct sockaddr* addr, s auto* current = Scheduler::current(); - socket->chmod(0777 & ~current->umask); - socket->chown(current->auth.euid, current->auth.egid); + m_metadata.mode = 0777 & ~current->umask; + m_metadata.uid = current->auth.euid; + m_metadata.gid = current->auth.egid; - auto rc = bind_socket_to_fs(path.chars(), current->auth, current->current_directory, socket); + auto rc = bind_socket_to_fs(path.chars(), current->auth, current->current_directory, SharedPtr { this }); if (rc.has_error()) { if (rc.error() == EEXIST) return err(EADDRINUSE); diff --git a/kernel/src/net/UnixSocket.h b/kernel/src/net/UnixSocket.h index 9d8114d5..69b23cfa 100644 --- a/kernel/src/net/UnixSocket.h +++ b/kernel/src/net/UnixSocket.h @@ -20,7 +20,7 @@ class UnixSocket : public Socket Result send(const u8*, usize, int) override; Result recv(u8*, usize, int) const override; - Result bind(SharedPtr, struct sockaddr*, socklen_t) override; + Result bind(struct sockaddr*, socklen_t) override; Result connect(Registers*, int, struct sockaddr*, socklen_t) override; Result> accept(Registers*, int, struct sockaddr**, socklen_t*) override; diff --git a/kernel/src/sys/exec.cpp b/kernel/src/sys/exec.cpp index d0c361a3..038f4b30 100644 --- a/kernel/src/sys/exec.cpp +++ b/kernel/src/sys/exec.cpp @@ -103,8 +103,8 @@ Result sys_execve(Registers* regs, SyscallArgs args) if (descriptor->description->flags & O_CLOEXEC) { descriptor = {}; } } - if (VFS::is_setuid(inode)) current->auth.euid = current->auth.suid = inode->uid(); - if (VFS::is_setgid(inode)) current->auth.egid = current->auth.sgid = inode->gid(); + if (VFS::is_setuid(inode)) current->auth.euid = current->auth.suid = inode->metadata().uid; + if (VFS::is_setgid(inode)) current->auth.egid = current->auth.sgid = inode->metadata().gid; current->name = path.chars(); diff --git a/kernel/src/sys/file.cpp b/kernel/src/sys/file.cpp index 6a7d2ddd..bfb1f949 100644 --- a/kernel/src/sys/file.cpp +++ b/kernel/src/sys/file.cpp @@ -64,7 +64,7 @@ Result sys_write(Registers*, SyscallArgs args) if (!descriptor.is_writable()) return err(EBADF); if (descriptor.should_append() && VFS::is_seekable(descriptor.inode())) - descriptor.offset = descriptor.inode()->size(); + descriptor.offset = descriptor.inode()->metadata().size; usize nwritten = TRY(descriptor.inode()->write(buf, descriptor.offset, size)); @@ -93,7 +93,7 @@ Result sys_lseek(Registers*, SyscallArgs args) { case SEEK_SET: new_offset = offset; break; case SEEK_CUR: new_offset = TRY(safe_add((long)descriptor.offset, offset)); break; - case SEEK_END: new_offset = TRY(safe_add((long)descriptor.inode()->size(), offset)); break; + case SEEK_END: new_offset = TRY(safe_add((long)descriptor.inode()->metadata().size, offset)); break; default: return err(EINVAL); } diff --git a/kernel/src/sys/getdents.cpp b/kernel/src/sys/getdents.cpp index 129799f2..0f5fa777 100644 --- a/kernel/src/sys/getdents.cpp +++ b/kernel/src/sys/getdents.cpp @@ -26,7 +26,7 @@ Result sys_getdents(Registers*, SyscallArgs args) descriptor.offset++; luna_dirent kent; - kent.inode = entry.inode->inode_number(); + kent.inode = entry.inode->metadata().inum; strlcpy(kent.name, entry.name.chars(), entry.name.length() + 1); if (!MemoryManager::copy_to_user_typed(ent, &kent)) return err(EFAULT); diff --git a/kernel/src/sys/id.cpp b/kernel/src/sys/id.cpp index c8c923d1..e6b116e4 100644 --- a/kernel/src/sys/id.cpp +++ b/kernel/src/sys/id.cpp @@ -153,9 +153,11 @@ Result sys_fchmodat(Registers*, SyscallArgs args) auto inode = TRY(current->resolve_atfile(dirfd, path, flags & AT_EMPTY_PATH, !(flags & AT_SYMLINK_NOFOLLOW))); - if (current->auth.euid != 0 && current->auth.euid != inode->uid()) return err(EPERM); + if (current->auth.euid != 0 && current->auth.euid != inode->metadata().uid) return err(EPERM); - TRY(inode->chmod(mode)); + auto metadata = inode->metadata(); + metadata.mode = mode; + TRY(inode->set_metadata(metadata)); return 0; } @@ -164,8 +166,8 @@ Result sys_fchownat(Registers*, SyscallArgs args) { int dirfd = (int)args[0]; auto path = TRY(MemoryManager::strdup_from_user(args[1])); - u32 uid = (u32)args[2]; - u32 gid = (u32)args[3]; + uid_t uid = (u32)args[2]; + gid_t gid = (u32)args[3]; int flags = (int)args[4]; auto* current = Scheduler::current(); @@ -174,7 +176,10 @@ Result sys_fchownat(Registers*, SyscallArgs args) if (current->auth.euid != 0) return err(EPERM); - TRY(inode->chown(uid == (u32)-1 ? inode->uid() : uid, gid == (u32)-1 ? inode->gid() : gid)); + auto metadata = inode->metadata(); + if (uid != (uid_t)-1) metadata.uid = uid; + if (gid != (gid_t)-1) metadata.gid = gid; + TRY(inode->set_metadata(metadata)); return 0; } diff --git a/kernel/src/sys/link.cpp b/kernel/src/sys/link.cpp index feeedc7d..813caf9a 100644 --- a/kernel/src/sys/link.cpp +++ b/kernel/src/sys/link.cpp @@ -26,8 +26,8 @@ Result sys_unlinkat(Registers*, SyscallArgs args) auto child = TRY(inode->find(basename.chars())); if (flags == AT_REMOVEDIR && child->type() != VFS::InodeType::Directory) return err(ENOTDIR); - if (current->auth.euid != 0 && VFS::is_sticky(inode) && current->auth.euid != inode->uid() && - current->auth.euid != child->uid()) + if (current->auth.euid != 0 && VFS::is_sticky(inode) && current->auth.euid != inode->metadata().uid && + current->auth.euid != child->metadata().uid) return err(EACCES); TRY(inode->remove_entry(basename.chars())); @@ -56,7 +56,10 @@ Result sys_symlinkat(Registers*, SyscallArgs args) TRY(VFS::validate_filename(child_name.view())); auto inode = TRY(parent_inode->fs()->create_symlink_inode(target.view())); - TRY(inode->chown(current->auth.euid, current->auth.egid)); + auto metadata = inode->metadata(); + metadata.uid = current->auth.euid; + metadata.gid = current->auth.egid; + TRY(inode->set_metadata(metadata)); TRY(parent_inode->add_entry(inode, child_name.chars())); return 0; diff --git a/kernel/src/sys/mkdir.cpp b/kernel/src/sys/mkdir.cpp index e961d0a3..acebd414 100644 --- a/kernel/src/sys/mkdir.cpp +++ b/kernel/src/sys/mkdir.cpp @@ -11,9 +11,12 @@ Result sys_mkdir(Registers*, SyscallArgs args) Thread* current = Scheduler::current(); - auto inode = TRY(VFS::create_directory(path.chars(), current->auth, current->current_directory)); - inode->chmod(mode & ~current->umask); - inode->chown(current->auth.euid, current->auth.egid); + auto inode = + TRY(VFS::create_directory(path.chars(), mode & ~current->umask, current->auth, current->current_directory)); + auto metadata = inode->metadata(); + metadata.uid = current->auth.euid; + metadata.gid = current->auth.egid; + TRY(inode->set_metadata(metadata)); return 0; } diff --git a/kernel/src/sys/mount.cpp b/kernel/src/sys/mount.cpp index b8e210a3..3071283e 100644 --- a/kernel/src/sys/mount.cpp +++ b/kernel/src/sys/mount.cpp @@ -17,7 +17,7 @@ Result sys_mount(Registers*, SyscallArgs args) auto get_source = [current, &source]() -> Result> { auto inode = TRY(VFS::resolve_path(source.chars(), current->auth, current->current_directory)); if (inode->type() != VFS::InodeType::BlockDevice) return err(ENOTBLK); - dev_t device_id = inode->device_id(); + dev_t device_id = inode->metadata().devid; return TRY(DeviceRegistry::fetch_special_device(luna_dev_major(device_id), luna_dev_minor(device_id))); }; diff --git a/kernel/src/sys/open.cpp b/kernel/src/sys/open.cpp index 0f359ec2..48a78596 100644 --- a/kernel/src/sys/open.cpp +++ b/kernel/src/sys/open.cpp @@ -37,9 +37,12 @@ Result sys_openat(Registers*, SyscallArgs args) { if (error == ENOENT && (flags & O_CREAT) && !path.is_empty()) { - inode = TRY(VFS::create_file(path.chars(), current->auth, parent_inode)); - inode->chmod(mode & ~current->umask); - inode->chown(current->auth.euid, current->auth.egid); + inode = TRY(VFS::create_file(path.chars(), mode & ~current->umask, current->auth, parent_inode)); + // FIXME: Pass these in create_file(). + auto metadata = inode->metadata(); + metadata.uid = current->auth.euid; + metadata.gid = current->auth.egid; + TRY(inode->set_metadata(metadata)); } else return err(error); @@ -60,9 +63,11 @@ Result sys_openat(Registers*, SyscallArgs args) if (flags & O_TMPFILE) { if (inode->type() != VFS::InodeType::Directory) return err(EINVAL); - inode = TRY(inode->fs()->create_file_inode()); - inode->chmod(mode); - inode->chown(current->auth.euid, current->auth.egid); + inode = TRY(inode->fs()->create_file_inode(mode & current->umask)); + auto metadata = inode->metadata(); + metadata.uid = current->auth.euid; + metadata.gid = current->auth.egid; + TRY(inode->set_metadata(metadata)); } if ((flags & O_WRONLY) && inode->fs() && inode->fs()->is_readonly()) return err(EROFS); diff --git a/kernel/src/sys/socket.cpp b/kernel/src/sys/socket.cpp index eed20db2..2132430b 100644 --- a/kernel/src/sys/socket.cpp +++ b/kernel/src/sys/socket.cpp @@ -43,7 +43,7 @@ Result sys_bind(Registers*, SyscallArgs args) auto socket = (SharedPtr)inode; - TRY(socket->bind(socket, (struct sockaddr*)&storage, addrlen)); + TRY(socket->bind((struct sockaddr*)&storage, addrlen)); return 0; } diff --git a/kernel/src/sys/stat.cpp b/kernel/src/sys/stat.cpp index 55e35699..9a57db92 100644 --- a/kernel/src/sys/stat.cpp +++ b/kernel/src/sys/stat.cpp @@ -38,14 +38,16 @@ Result sys_fstatat(Registers*, SyscallArgs args) stat kstat; - kstat.st_ino = inode->inode_number(); - kstat.st_mode = make_mode(inode->mode(), inode->type()); - kstat.st_nlink = inode->nlinks(); - kstat.st_uid = inode->uid(); - kstat.st_gid = inode->gid(); - kstat.st_size = inode->size(); + const auto& metadata = inode->metadata(); + + kstat.st_ino = metadata.inum; + kstat.st_mode = make_mode(metadata.mode, inode->type()); + kstat.st_nlink = metadata.nlinks; + kstat.st_uid = metadata.uid; + kstat.st_gid = metadata.gid; + kstat.st_size = metadata.size; kstat.st_dev = inode->fs() ? inode->fs()->host_device_id() : 0; - kstat.st_rdev = inode->device_id(); + kstat.st_rdev = metadata.devid; if (!MemoryManager::copy_to_user_typed(st, &kstat)) return err(EFAULT);