diff --git a/kernel/include/kernel/FS/TmpFS/Inode.h b/kernel/include/kernel/FS/TmpFS/Inode.h index 4bce88b2..287f4264 100644 --- a/kernel/include/kernel/FS/TmpFS/Inode.h +++ b/kernel/include/kernel/FS/TmpFS/Inode.h @@ -12,7 +12,7 @@ namespace Kernel { template - concept for_each_entry_callback = requires(F func, const TmpDirectoryEntry& entry) + concept for_each_valid_entry_callback = requires(F func, TmpDirectoryEntry& entry) { requires BAN::is_same_v; }; @@ -107,8 +107,8 @@ namespace Kernel BAN::ErrorOr link_inode(TmpInode&, BAN::StringView); - template - void for_each_entry(F callback); + template + void for_each_valid_entry(F callback); friend class TmpInode; }; diff --git a/kernel/kernel/FS/TmpFS/Inode.cpp b/kernel/kernel/FS/TmpFS/Inode.cpp index 8db6d538..9569b6cf 100644 --- a/kernel/kernel/FS/TmpFS/Inode.cpp +++ b/kernel/kernel/FS/TmpFS/Inode.cpp @@ -260,9 +260,7 @@ namespace Kernel { ino_t result = 0; - for_each_entry([&](const TmpDirectoryEntry& entry) { - if (entry.type == DT_UNKNOWN) - return BAN::Iteration::Continue; + for_each_valid_entry([&](TmpDirectoryEntry& entry) { if (entry.name_sv() != name) return BAN::Iteration::Continue; result = entry.ino; @@ -339,7 +337,35 @@ namespace Kernel BAN::ErrorOr TmpDirectoryInode::unlink_impl(BAN::StringView) { - return BAN::Error::from_errno(ENOTSUP); + ino_t entry_ino = 0; + + for_each_valid_entry([&](TmpDirectoryEntry& entry) { + if (entry.name_sv() != name) + return BAN::Iteration::Continue; + + // get ino of entry + entry_ino = entry.ino; + + // invalidate the entry + entry.ino = 0; + entry.type = DT_UNKNOWN; + + return BAN::Iteration::Break; + }); + + if (entry_ino == 0) + return BAN::Error::from_errno(ENOENT); + + // FIXME: this should be able to fail + auto inode = MUST(m_fs.open_inode(entry_ino)); + + ASSERT(inode->nlink() > 0); + inode->m_inode_info.nlink--; + + if (inode->nlink() == 0 || (inode->mode().ifdir() && inode->nlink() <= 2)) + m_fs.remove_from_cache(inode); + + return {}; } BAN::ErrorOr TmpDirectoryInode::link_inode(TmpInode& inode, BAN::StringView name) @@ -391,8 +417,8 @@ namespace Kernel return {}; } - template - void TmpDirectoryInode::for_each_entry(F callback) + template + void TmpDirectoryInode::for_each_valid_entry(F callback) { bool done = false; for (size_t data_block_index = 0; !done && data_block_index * blksize() < (size_t)size(); data_block_index++) @@ -405,15 +431,18 @@ namespace Kernel while (bytespan.size() > 0) { auto& entry = bytespan.as(); - switch (callback(entry)) + if (entry.type != DT_UNKNOWN) { - case BAN::Iteration::Continue: - break; - case BAN::Iteration::Break: - done = true; - return; - default: - ASSERT_NOT_REACHED(); + switch (callback(entry)) + { + case BAN::Iteration::Continue: + break; + case BAN::Iteration::Break: + done = true; + return; + default: + ASSERT_NOT_REACHED(); + } } bytespan = bytespan.slice(entry.rec_len); }