From 3b39a2f71b906e2f303a58b9b9050e2c89b62421 Mon Sep 17 00:00:00 2001 From: Undefine Date: Thu, 18 Jan 2024 21:04:03 +0100 Subject: [PATCH] Kernel/FATFS: Implement add_child --- Kernel/FileSystem/FATFS/Inode.cpp | 35 +++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/Kernel/FileSystem/FATFS/Inode.cpp b/Kernel/FileSystem/FATFS/Inode.cpp index 3ab848d7689..7d26015ac8d 100644 --- a/Kernel/FileSystem/FATFS/Inode.cpp +++ b/Kernel/FileSystem/FATFS/Inode.cpp @@ -568,9 +568,40 @@ ErrorOr> FATInode::create_child(StringView name, mode_t mod return TRY(FATInode::create(fs(), entry, entries[lfn_entries.size()], lfn_entries)); } -ErrorOr FATInode::add_child(Inode&, StringView, mode_t) +ErrorOr FATInode::add_child(Inode& inode, StringView name, mode_t mode) { - return EROFS; + VERIFY(has_flag(m_entry.attributes, FATAttributes::Directory)); + VERIFY(inode.fsid() == fsid()); + + // FIXME: There's a lot of similar code between this function and create_child, we should try to factor out some of the common code. + + dbgln_if(FAT_DEBUG, "FATInode[{}]::add_child(): appending inode {} as \"{}\"", identifier(), inode.identifier(), name); + + auto entry = bit_cast(&inode)->m_entry; + create_83_filename_for(entry, name); + + // TODO: We should set the hidden attribute if the file starts with a dot or read only (the same way Linux does this). + if (mode & S_IFDIR) + entry.attributes |= FATAttributes::Directory; + + // FIXME: Set the dates + + // FIXME: For some filenames lfn entries are not necessary + auto lfn_entries = TRY(create_lfn_entries(name, lfn_entry_checksum(entry))); + + MutexLocker locker(m_inode_lock); + + auto entries = TRY(allocate_entries(lfn_entries.size() + 1)); + + // FIXME: If we fail here we should clean up the entries we wrote + TRY(fs().write_block(entries[lfn_entries.size()].block, UserOrKernelBuffer::for_kernel_buffer(bit_cast(&entry)), sizeof(FATEntry), entries[lfn_entries.size()].entry * sizeof(FATEntry))); + + for (u32 i = 0; i < lfn_entries.size(); i++) { + auto location = entries[lfn_entries.size() - i - 1]; + TRY(fs().write_block(location.block, UserOrKernelBuffer::for_kernel_buffer(bit_cast(&lfn_entries[i])), sizeof(FATLongFileNameEntry), location.entry * sizeof(FATLongFileNameEntry))); + } + + return {}; } ErrorOr FATInode::remove_child(StringView)