Kernel: Implement Ext2 directory creation

This commit is contained in:
Bananymous 2023-10-25 19:37:04 +03:00
parent 6ee5576dcc
commit e85f9ac6a1
2 changed files with 87 additions and 31 deletions

View File

@ -31,6 +31,7 @@ namespace Kernel
virtual BAN::ErrorOr<BAN::RefPtr<Inode>> find_inode_impl(BAN::StringView) override;
virtual BAN::ErrorOr<void> list_next_inodes_impl(off_t, DirectoryEntryList*, size_t) override;
virtual BAN::ErrorOr<void> create_file_impl(BAN::StringView, mode_t, uid_t, gid_t) override;
virtual BAN::ErrorOr<void> create_directory_impl(BAN::StringView, mode_t, uid_t, gid_t) override;
virtual BAN::ErrorOr<BAN::String> link_target_impl() override;
@ -42,6 +43,8 @@ namespace Kernel
private:
uint32_t fs_block_of_data_block_index(uint32_t data_block_index);
BAN::ErrorOr<void> link_inode_to_directory(Ext2Inode&, BAN::StringView name);
BAN::ErrorOr<uint32_t> allocate_new_block();
BAN::ErrorOr<void> sync();

View File

@ -317,7 +317,86 @@ namespace Kernel
return {};
}
static bool mode_has_valid_type(mode_t mode)
{
switch (mode & Inode::Mode::TYPE_MASK)
{
case Inode::Mode::IFIFO: return true;
case Inode::Mode::IFCHR: return true;
case Inode::Mode::IFDIR: return true;
case Inode::Mode::IFBLK: return true;
case Inode::Mode::IFREG: return true;
case Inode::Mode::IFLNK: return true;
case Inode::Mode::IFSOCK: return true;
}
return false;
}
static Ext2::Inode initialize_new_inode_info(mode_t mode, uid_t uid, gid_t gid)
{
ASSERT(mode_has_valid_type(mode));
timespec current_time = SystemTimer::get().real_time();
return Ext2::Inode
{
.mode = (uint16_t)mode,
.uid = (uint16_t)uid,
.size = 0,
.atime = (uint32_t)current_time.tv_sec,
.ctime = (uint32_t)current_time.tv_sec,
.mtime = (uint32_t)current_time.tv_sec,
.dtime = 0,
.gid = (uint16_t)gid,
.links_count = 0,
.blocks = 0,
.flags = 0,
.osd1 = 0,
.block = {},
.generation = 0,
.file_acl = 0,
.dir_acl = 0,
.faddr = 0,
.osd2 = {}
};
}
BAN::ErrorOr<void> Ext2Inode::create_file_impl(BAN::StringView name, mode_t mode, uid_t uid, gid_t gid)
{
// FIXME: handle errors
ASSERT(this->mode().ifdir());
if (!(Mode(mode).ifreg()))
return BAN::Error::from_errno(ENOTSUP);
const uint32_t new_ino = TRY(m_fs.create_inode(initialize_new_inode_info(mode, uid, gid)));
auto inode = MUST(Ext2Inode::create(m_fs, new_ino));
MUST(link_inode_to_directory(*inode, name));
return {};
}
BAN::ErrorOr<void> Ext2Inode::create_directory_impl(BAN::StringView name, mode_t mode, uid_t uid, gid_t gid)
{
// FIXME: handle errors
ASSERT(this->mode().ifdir());
ASSERT(Mode(mode).ifdir());
const uint32_t new_ino = TRY(m_fs.create_inode(initialize_new_inode_info(mode, uid, gid)));
auto inode = MUST(Ext2Inode::create(m_fs, new_ino));
MUST(inode->link_inode_to_directory(*inode, "."sv));
MUST(inode->link_inode_to_directory(*this, ".."sv));
MUST(link_inode_to_directory(*inode, name));
return {};
}
BAN::ErrorOr<void> Ext2Inode::link_inode_to_directory(Ext2Inode& inode, BAN::StringView name)
{
if (!this->mode().ifdir())
return BAN::Error::from_errno(ENOTDIR);
@ -325,9 +404,6 @@ namespace Kernel
if (name.size() > 255)
return BAN::Error::from_errno(ENAMETOOLONG);
if (!(Mode(mode).ifreg()))
return BAN::Error::from_errno(EINVAL);
if (m_inode.flags & Ext2::Enum::INDEX_FL)
{
dwarnln("file creation to indexed directory not supported");
@ -340,39 +416,13 @@ namespace Kernel
if (error_or.error().get_error_code() != ENOENT)
return error_or.error();
timespec current_time = SystemTimer::get().real_time();
Ext2::Inode ext2_inode
{
.mode = (uint16_t)mode,
.uid = (uint16_t)uid,
.size = 0,
.atime = (uint32_t)current_time.tv_sec,
.ctime = (uint32_t)current_time.tv_sec,
.mtime = (uint32_t)current_time.tv_sec,
.dtime = 0,
.gid = (uint16_t)gid,
.links_count = 1,
.blocks = 0,
.flags = 0,
.osd1 = 0,
.block = {},
.generation = 0,
.file_acl = 0,
.dir_acl = 0,
.faddr = 0,
.osd2 = {}
};
const uint32_t inode_index = TRY(m_fs.create_inode(ext2_inode));
const uint32_t block_size = m_fs.block_size();
auto block_buffer = m_fs.get_block_buffer();
auto write_inode = [&](uint32_t entry_offset, uint32_t entry_rec_len)
{
auto typed_mode = Mode(mode);
auto typed_mode = inode.mode();
uint8_t file_type = (m_fs.superblock().rev_level == Ext2::Enum::GOOD_OLD_REV) ? 0
: typed_mode.ifreg() ? Ext2::Enum::REG_FILE
: typed_mode.ifdir() ? Ext2::Enum::DIR
@ -384,11 +434,14 @@ namespace Kernel
: 0;
auto& new_entry = *(Ext2::LinkedDirectoryEntry*)(block_buffer.data() + entry_offset);
new_entry.inode = inode_index;
new_entry.inode = inode.ino();
new_entry.rec_len = entry_rec_len;
new_entry.name_len = name.size();
new_entry.file_type = file_type;
memcpy(new_entry.name, name.data(), name.size());
inode.m_inode.links_count++;
MUST(inode.sync());
};
uint32_t block_index = 0;