kernel/VFS: Rework the metadata system so that there is a single metadata struct
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
apio 2023-08-01 17:20:28 +02:00
parent 4c87d72b44
commit dc35c42371
Signed by: apio
GPG Key ID: B8A7D06E42258954
28 changed files with 203 additions and 494 deletions

View File

@ -18,17 +18,15 @@ void InitRD::initialize()
g_initrd.initialize((void*)virtual_initrd_address, bootboot.initrd_size);
}
static Result<void> vfs_create_dir_if_not_exists(const char* path, mode_t mode, uid_t uid, gid_t gid)
static Result<void> 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<void> 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));
}
}

View File

@ -42,39 +42,14 @@ class MountInode : public VFS::Inode, public LinkedListNode<MountInode>
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<void> 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<void> chmod(mode_t mode) override
{
return m_mount_root_inode->chmod(mode);
}
Result<void> 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<MountInode>
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<MountInode>
return m_mount_root_inode->remove_entry(name);
}
Result<SharedPtr<VFS::Inode>> create_file(const char* name) override
Result<SharedPtr<VFS::Inode>> 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<SharedPtr<VFS::Inode>> create_subdirectory(const char* name) override
Result<SharedPtr<VFS::Inode>> 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<void> add_entry(SharedPtr<VFS::Inode> inode, const char* name) override

View File

@ -14,8 +14,14 @@ Result<void> Pipe::create(SharedPtr<VFS::Inode>& rpipe, SharedPtr<VFS::Inode>& 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;

View File

@ -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<void> chmod(mode_t) override
{
return err(ENOTSUP);
}
Result<void> 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<Pipe> 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;

View File

@ -69,7 +69,8 @@ namespace VFS
return resolve_path_impl(path, auth, current_inode, follow_last_symlink, symlinks_followed);
}
Result<SharedPtr<Inode>> create_directory(const char* path, Credentials auth, SharedPtr<Inode> working_directory)
Result<SharedPtr<Inode>> create_directory(const char* path, mode_t mode, Credentials auth,
SharedPtr<Inode> 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<SharedPtr<Inode>> create_file(const char* path, Credentials auth, SharedPtr<Inode> working_directory)
Result<SharedPtr<Inode>> create_file(const char* path, mode_t mode, Credentials auth,
SharedPtr<Inode> 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<void> 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> 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> 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> inode)
{
return inode->mode() & S_ISUID;
return inode->metadata().mode & S_ISUID;
}
bool is_setgid(SharedPtr<Inode> inode)
{
return inode->mode() & S_ISGID;
return inode->metadata().mode & S_ISGID;
}
bool is_sticky(SharedPtr<Inode> inode)
{
return inode->mode() & S_ISVTX;
return inode->metadata().mode & S_ISVTX;
}
bool is_seekable(SharedPtr<Inode> inode)

View File

@ -1,5 +1,7 @@
#pragma once
#include "arch/Timer.h"
#include <bits/makedev.h>
#include <bits/timespec.h>
#include <luna/SharedPtr.h>
#include <luna/StaticString.h>
#include <luna/StringView.h>
@ -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<Inode> root_inode() const = 0;
virtual Result<SharedPtr<Inode>> create_file_inode() = 0;
virtual Result<SharedPtr<Inode>> create_file_inode(mode_t mode) = 0;
virtual Result<SharedPtr<Inode>> create_dir_inode(SharedPtr<Inode> parent) = 0;
virtual Result<SharedPtr<Inode>> create_dir_inode(SharedPtr<Inode> parent, mode_t mode) = 0;
virtual Result<SharedPtr<Inode>> create_device_inode(u32 major, u32 minor) = 0;
virtual Result<SharedPtr<Inode>> create_device_inode(u32 major, u32 minor, mode_t mode) = 0;
virtual Result<SharedPtr<Inode>> create_symlink_inode(StringView link) = 0;
@ -101,9 +118,9 @@ namespace VFS
virtual Option<DirectoryEntry> get(usize index) const = 0;
virtual Result<SharedPtr<Inode>> create_file(const char* name) = 0;
virtual Result<SharedPtr<Inode>> create_file(const char* name, mode_t mode) = 0;
virtual Result<SharedPtr<Inode>> create_subdirectory(const char* name) = 0;
virtual Result<SharedPtr<Inode>> create_subdirectory(const char* name, mode_t mode) = 0;
virtual Result<void> add_entry(SharedPtr<Inode> 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<void> 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<void> chmod(mode_t mode) = 0;
virtual Result<void> 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<SharedPtr<Inode>> find(const char*) const override
@ -201,12 +201,12 @@ namespace VFS
return {};
}
Result<SharedPtr<Inode>> create_file(const char*) override
Result<SharedPtr<Inode>> create_file(const char*, mode_t) override
{
return err(ENOTDIR);
}
Result<SharedPtr<Inode>> create_subdirectory(const char*) override
Result<SharedPtr<Inode>> 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<SharedPtr<Inode>> find(const char*) const override
@ -257,12 +257,12 @@ namespace VFS
return {};
}
Result<SharedPtr<Inode>> create_file(const char*) override
Result<SharedPtr<Inode>> create_file(const char*, mode_t) override
{
return err(ENOTDIR);
}
Result<SharedPtr<Inode>> create_subdirectory(const char*) override
Result<SharedPtr<Inode>> create_subdirectory(const char*, mode_t) override
{
return err(ENOTDIR);
}
@ -299,10 +299,10 @@ namespace VFS
SharedPtr<VFS::Inode> working_directory = {},
bool follow_last_symlink = true);
Result<SharedPtr<Inode>> create_directory(const char* path, Credentials auth,
Result<SharedPtr<Inode>> create_directory(const char* path, mode_t mode, Credentials auth,
SharedPtr<VFS::Inode> working_directory = {});
Result<SharedPtr<Inode>> create_file(const char* path, Credentials auth,
Result<SharedPtr<Inode>> create_file(const char* path, mode_t mode, Credentials auth,
SharedPtr<VFS::Inode> working_directory = {});
Result<void> validate_filename(StringView name);

View File

@ -36,8 +36,7 @@ namespace DeviceRegistry
Result<void> create_special_device_inode(SharedPtr<VFS::FileSystem> 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 {};

View File

@ -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,

View File

@ -127,17 +127,17 @@ namespace Ext2
return m_root_inode;
}
Result<SharedPtr<VFS::Inode>> create_file_inode() override
Result<SharedPtr<VFS::Inode>> create_file_inode(mode_t) override
{
return err(EROFS);
}
Result<SharedPtr<VFS::Inode>> create_dir_inode(SharedPtr<VFS::Inode>) override
Result<SharedPtr<VFS::Inode>> create_dir_inode(SharedPtr<VFS::Inode>, mode_t) override
{
return err(EROFS);
}
Result<SharedPtr<VFS::Inode>> create_device_inode(u32, u32) override
Result<SharedPtr<VFS::Inode>> create_device_inode(u32, u32, mode_t) override
{
return err(EROFS);
}

View File

@ -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<usize> 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<u8>(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)
{

View File

@ -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<void> chmod(mode_t) override
{
return err(EROFS);
}
Result<void> chown(u32, u32) override
Result<void> set_metadata(const VFS::InodeMetadata&) override
{
return err(EROFS);
}
@ -87,14 +55,14 @@ namespace Ext2
Option<VFS::DirectoryEntry> get(usize) const override;
Result<SharedPtr<VFS::Inode>> create_file(const char*) override
Result<SharedPtr<VFS::Inode>> create_file(const char*, mode_t) override
{
if (m_type != VFS::InodeType::Directory) return err(ENOTDIR);
return err(EROFS);
}
Result<SharedPtr<VFS::Inode>> create_subdirectory(const char*) override
Result<SharedPtr<VFS::Inode>> create_subdirectory(const char*, mode_t) override
{
if (m_type != VFS::InodeType::Directory) return err(ENOTDIR);

View File

@ -10,8 +10,7 @@ namespace TmpFS
Result<SharedPtr<VFS::FileSystem>> FileSystem::create()
{
SharedPtr<FileSystem> fs = TRY(adopt_shared_if_nonnull(new (std::nothrow) FileSystem()));
SharedPtr<VFS::Inode> root = TRY(fs->create_dir_inode({}));
root->chmod(0755);
SharedPtr<VFS::Inode> root = TRY(fs->create_dir_inode({}, 0755));
fs->set_root(root);
return (SharedPtr<VFS::FileSystem>)fs;
}
@ -21,11 +20,12 @@ namespace TmpFS
return m_next_inode_number++;
}
Result<SharedPtr<VFS::Inode>> FileSystem::create_file_inode()
Result<SharedPtr<VFS::Inode>> FileSystem::create_file_inode(mode_t mode)
{
SharedPtr<FileInode> inode = TRY(make_shared<FileInode>());
inode->set_fs(*this, {});
inode->set_inode_number(m_next_inode_number++, {});
inode->m_metadata.mode = mode;
return (SharedPtr<VFS::Inode>)inode;
}
@ -38,7 +38,7 @@ namespace TmpFS
return (SharedPtr<VFS::Inode>)inode;
}
Result<SharedPtr<VFS::Inode>> FileSystem::create_dir_inode(SharedPtr<VFS::Inode> parent)
Result<SharedPtr<VFS::Inode>> FileSystem::create_dir_inode(SharedPtr<VFS::Inode> parent, mode_t mode)
{
SharedPtr<DirInode> inode = TRY(make_shared<DirInode>());
@ -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<VFS::Inode>)inode;
}
Result<SharedPtr<VFS::Inode>> FileSystem::create_device_inode(u32 major, u32 minor)
Result<SharedPtr<VFS::Inode>> FileSystem::create_device_inode(u32 major, u32 minor, mode_t mode)
{
SharedPtr<Device> 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<VFS::Inode>)inode;
}

View File

@ -13,9 +13,9 @@ namespace TmpFS
return m_root_inode;
}
Result<SharedPtr<VFS::Inode>> create_file_inode() override;
Result<SharedPtr<VFS::Inode>> create_dir_inode(SharedPtr<VFS::Inode> parent) override;
Result<SharedPtr<VFS::Inode>> create_device_inode(u32 major, u32 minor) override;
Result<SharedPtr<VFS::Inode>> create_file_inode(mode_t mode) override;
Result<SharedPtr<VFS::Inode>> create_dir_inode(SharedPtr<VFS::Inode> parent, mode_t mode) override;
Result<SharedPtr<VFS::Inode>> create_device_inode(u32 major, u32 minor, mode_t mode) override;
Result<SharedPtr<VFS::Inode>> create_symlink_inode(StringView link) override;
Result<u64> allocate_inode_number() override;

View File

@ -62,18 +62,18 @@ namespace TmpFS
return {};
}
Result<SharedPtr<VFS::Inode>> DirInode::create_file(const char* name)
Result<SharedPtr<VFS::Inode>> 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<SharedPtr<VFS::Inode>> DirInode::create_subdirectory(const char* name)
Result<SharedPtr<VFS::Inode>> 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();
}
}

View File

@ -20,68 +20,27 @@ namespace TmpFS
void set_inode_number(usize inum, Badge<FileSystem>)
{
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<usize> read(u8*, usize, usize) const override;
Result<usize> write(const u8*, usize, usize) override;
Result<void> 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<void> chmod(mode_t mode) override
{
m_mode = mode;
return {};
}
Result<void> 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<FileSystem>)
{
m_inode_number = inum;
m_metadata.inum = inum;
}
Result<void> set_link(StringView link, Badge<FileSystem>)
@ -127,11 +83,6 @@ namespace TmpFS
return m_fs;
}
usize inode_number() const override
{
return m_inode_number;
}
Result<usize> 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<void> chmod(mode_t) override
{
return {};
}
Result<void> 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<StringView> 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<FileSystem>)
{
m_inode_number = inum;
m_metadata.inum = inum;
}
void set_device(SharedPtr<Device> device, Badge<FileSystem>)
@ -237,7 +149,7 @@ namespace TmpFS
void set_device_id(dev_t id, Badge<FileSystem>)
{
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<usize> 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<void> chmod(mode_t mode) override
{
m_mode = mode;
return {};
}
Result<void> 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<Device> 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<FileSystem>)
{
m_inode_number = inum;
m_metadata.inum = inum;
}
void set_self(SharedPtr<VFS::Inode> self, Badge<FileSystem>)
@ -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<void> chmod(mode_t mode) override
{
m_mode = mode;
return {};
}
Result<void> 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<void> remove_entry(const char* name) override;
Result<SharedPtr<VFS::Inode>> create_file(const char* name) override;
Result<SharedPtr<VFS::Inode>> create_subdirectory(const char* name) override;
Result<SharedPtr<VFS::Inode>> create_file(const char* name, mode_t mode) override;
Result<SharedPtr<VFS::Inode>> create_subdirectory(const char* name, mode_t mode) override;
Result<void> add_entry(SharedPtr<VFS::Inode> inode, const char* name);
Result<void> replace_entry(SharedPtr<VFS::Inode> 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<VFS::Inode> m_self;
Vector<VFS::DirectoryEntry> m_entries;
friend class FileSystem;
};
}

View File

@ -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<usize> read(u8* buf, usize, usize length) const override
{
return recv(buf, length, 0);
@ -48,7 +43,7 @@ class Socket : public VFS::FileInode
virtual Result<usize> recv(u8*, usize, int) const = 0;
virtual Result<void> bind(SharedPtr<Socket>, struct sockaddr*, socklen_t) = 0;
virtual Result<void> bind(struct sockaddr*, socklen_t) = 0;
virtual Result<void> connect(Registers*, int, struct sockaddr*, socklen_t) = 0;
virtual Result<SharedPtr<OpenFileDescription>> 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<void> chmod(mode_t mode) override
{
m_mode = mode;
return {};
}
Result<void> 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 };
};

View File

@ -71,7 +71,7 @@ static Result<void> bind_socket_to_fs(const char* path, Credentials auth, Shared
return parent_inode->add_entry(socket, child_name.chars());
}
Result<void> UnixSocket::bind(SharedPtr<Socket> socket, struct sockaddr* addr, socklen_t addrlen)
Result<void> 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<void> UnixSocket::bind(SharedPtr<Socket> 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<Socket> { this });
if (rc.has_error())
{
if (rc.error() == EEXIST) return err(EADDRINUSE);

View File

@ -20,7 +20,7 @@ class UnixSocket : public Socket
Result<usize> send(const u8*, usize, int) override;
Result<usize> recv(u8*, usize, int) const override;
Result<void> bind(SharedPtr<Socket>, struct sockaddr*, socklen_t) override;
Result<void> bind(struct sockaddr*, socklen_t) override;
Result<void> connect(Registers*, int, struct sockaddr*, socklen_t) override;
Result<SharedPtr<OpenFileDescription>> accept(Registers*, int, struct sockaddr**, socklen_t*) override;

View File

@ -103,8 +103,8 @@ Result<u64> 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();

View File

@ -64,7 +64,7 @@ Result<u64> 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<u64> 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);
}

View File

@ -26,7 +26,7 @@ Result<u64> 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);

View File

@ -153,9 +153,11 @@ Result<u64> 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<u64> 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<u64> 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;
}

View File

@ -26,8 +26,8 @@ Result<u64> 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<u64> 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;

View File

@ -11,9 +11,12 @@ Result<u64> 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;
}

View File

@ -17,7 +17,7 @@ Result<u64> sys_mount(Registers*, SyscallArgs args)
auto get_source = [current, &source]() -> Result<SharedPtr<Device>> {
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)));
};

View File

@ -37,9 +37,12 @@ Result<u64> 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<u64> 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);

View File

@ -43,7 +43,7 @@ Result<u64> sys_bind(Registers*, SyscallArgs args)
auto socket = (SharedPtr<Socket>)inode;
TRY(socket->bind(socket, (struct sockaddr*)&storage, addrlen));
TRY(socket->bind((struct sockaddr*)&storage, addrlen));
return 0;
}

View File

@ -38,14 +38,16 @@ Result<u64> 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);