diff options
| author | Amlal El Mahrouss <amlal@nekernel.org> | 2025-11-24 03:02:43 +0100 |
|---|---|---|
| committer | Amlal El Mahrouss <amlal@nekernel.org> | 2025-11-24 03:02:43 +0100 |
| commit | 83d870e58457a1d335a1d9b9966a6a1887cc297b (patch) | |
| tree | 72888f88c7728c82f3f6df1f4f70591de15eab36 /dev/kernel/src/FS | |
| parent | ab37adbacf0f33845804c788b39680cd754752a8 (diff) | |
feat! breaking changes on kernel sources.
Signed-off-by: Amlal El Mahrouss <amlal@nekernel.org>
Diffstat (limited to 'dev/kernel/src/FS')
| -rw-r--r-- | dev/kernel/src/FS/Ext2+IFS.cc | 1555 | ||||
| -rw-r--r-- | dev/kernel/src/FS/NeFS+FileMgr.cc | 276 | ||||
| -rw-r--r-- | dev/kernel/src/FS/NeFS+FileSystemParser.cc | 870 | ||||
| -rw-r--r-- | dev/kernel/src/FS/OpenHeFS+FileMgr.cc | 191 | ||||
| -rw-r--r-- | dev/kernel/src/FS/OpenHeFS+FileSystemParser.cc | 1160 |
5 files changed, 0 insertions, 4052 deletions
diff --git a/dev/kernel/src/FS/Ext2+IFS.cc b/dev/kernel/src/FS/Ext2+IFS.cc deleted file mode 100644 index 106229f7..00000000 --- a/dev/kernel/src/FS/Ext2+IFS.cc +++ /dev/null @@ -1,1555 +0,0 @@ -/* ======================================== - - Copyright (C) 2024-2025, Amlal El Mahrouss, licensed under the Apache 2.0 license. - -======================================== */ - -#ifndef __NE_MINIMAL_OS__ -#ifdef __FSKIT_INCLUDES_EXT2__ - -#include <FSKit/Ext2+IFS.h> -#include <FSKit/Ext2.h> -#include <KernelKit/DebugOutput.h> -#include <KernelKit/FileMgr.h> -#include <KernelKit/HeapMgr.h> -#include <NeKit/ErrorOr.h> -#include <NeKit/KString.h> -#include <NeKit/KernelPanic.h> -#include <NeKit/Utils.h> - -constexpr static UInt32 EXT2_DIRECT_BLOCKS = 12; -constexpr static UInt32 EXT2_SINGLE_INDIRECT_INDEX = 12; -constexpr static UInt32 EXT2_DOUBLE_INDIRECT_INDEX = 13; -constexpr ATTRIBUTE(unused) static UInt32 EXT2_TRIPLE_INDIRECT_INDEX = 14; -constexpr static UInt32 EXT2_ROOT_INODE = 2; -constexpr ATTRIBUTE(unused) static UInt32 EXT2_SUPERBLOCK_BLOCK = 1; -constexpr static UInt32 EXT2_GROUP_DESC_BLOCK_SMALL = 2; -constexpr static UInt32 EXT2_GROUP_DESC_BLOCK_LARGE = 1; - -static inline SizeT ext2_min(SizeT a, SizeT b) { - return a < b ? a : b; -} - -struct Ext2GroupInfo { - EXT2_GROUP_DESCRIPTOR* groupDesc; - UInt32 groupDescriptorBlock; - UInt32 offsetInGroupDescBlock; - UInt8* blockBuffer; -}; - -// Convert EXT2 block number -> LBA (sector index) for Drive I/O. -static inline UInt32 ext2_block_to_lba(Ext2Context* ctx, UInt32 blockNumber) { - if (!ctx || !ctx->drive) return 0; - UInt32 blockSize = ctx->BlockSize(); - UInt32 sectorSize = ctx->drive->fSectorSz; - UInt32 sectorsPerBlock = blockSize / sectorSize; - return blockNumber * sectorsPerBlock; -} - -// Read a block and return a pointer to its content -static ErrorOr<UInt32*> ext2_read_block_ptr(Ext2Context* ctx, UInt32 blockNumber) { - if (!ctx || !ctx->drive || !ctx->superblock) return ErrorOr<UInt32*>(kErrorInvalidData); - - UInt32 blockSize = ctx->BlockSize(); - auto buf = (UInt32*) mm_alloc_ptr(blockSize, true, false); - if (!buf) return ErrorOr<UInt32*>(kErrorHeapOutOfMemory); - - UInt32 lba = ext2_block_to_lba(ctx, blockNumber); - if (!ext2_read_block(ctx->drive, lba, buf, blockSize)) { - mm_free_ptr(buf); - return ErrorOr<UInt32*>(kErrorDisk); - } - return ErrorOr<UInt32*>(buf); -} - -// Get the block address for a given logical block index -static ErrorOr<UInt32> ext2_get_block_address(Ext2Context* ctx, Ext2Node* node, - UInt32 logicalIndex) { - if (!ctx || !node || !ctx->drive) return ErrorOr<UInt32>(kErrorInvalidData); - - UInt32 blockSize = ctx->BlockSize(); - UInt32 pointersPerBlock = blockSize / sizeof(UInt32); - - // Direct blocks - if (logicalIndex < EXT2_DIRECT_BLOCKS) { - UInt32 bn = node->inode.fBlock[logicalIndex]; - if (bn == 0) return ErrorOr<UInt32>(kErrorInvalidData); - return ErrorOr<UInt32>(bn); - } - - // Single indirect blocks - if (logicalIndex < (EXT2_DIRECT_BLOCKS + pointersPerBlock)) { - UInt32 iblock = node->inode.fBlock[EXT2_SINGLE_INDIRECT_INDEX]; - if (iblock == 0) return ErrorOr<UInt32>(kErrorInvalidData); - - auto res = ext2_read_block_ptr(ctx, iblock); - if (!res) return ErrorOr<UInt32>(res.Error()); - - // Using dereference operator - UInt32* ptr = *res.Leak(); // operator* returns T (UInt32*) - - UInt32 val = ptr[logicalIndex - EXT2_DIRECT_BLOCKS]; - mm_free_ptr(ptr); - - if (val == 0) return ErrorOr<UInt32>(kErrorInvalidData); - return ErrorOr<UInt32>(val); - } - - // Double indirect blocks - UInt32 doubleStart = EXT2_DIRECT_BLOCKS + pointersPerBlock; - UInt32 doubleSpan = pointersPerBlock * pointersPerBlock; - if (logicalIndex < (doubleStart + doubleSpan)) { - UInt32 db = node->inode.fBlock[EXT2_DOUBLE_INDIRECT_INDEX]; - if (db == 0) return ErrorOr<UInt32>(kErrorInvalidData); - - auto dblRes = ext2_read_block_ptr(ctx, db); - if (!dblRes) return ErrorOr<UInt32>(dblRes.Error()); - - UInt32* dblPtr = *dblRes.Leak(); - - UInt32 idxWithin = logicalIndex - doubleStart; - UInt32 firstIdx = idxWithin / pointersPerBlock; - UInt32 secondIdx = idxWithin % pointersPerBlock; - UInt32 singleBlockNum = dblPtr[firstIdx]; - - mm_free_ptr(dblPtr); - if (singleBlockNum == 0) return ErrorOr<UInt32>(kErrorInvalidData); - - auto singleRes = ext2_read_block_ptr(ctx, singleBlockNum); - if (!singleRes) return ErrorOr<UInt32>(singleRes.Error()); - - UInt32* singlePtr = *singleRes.Leak(); - UInt32 val = singlePtr[secondIdx]; - mm_free_ptr(singlePtr); - - if (val == 0) return ErrorOr<UInt32>(kErrorInvalidData); - return ErrorOr<UInt32>(val); - } - - return ErrorOr<UInt32>(kErrorUnimplemented); -} - -static ErrorOr<voidPtr> ext2_read_inode_data(Ext2Context* ctx, Ext2Node* node, SizeT size) { - if (!ctx || !ctx->drive || !node || size == 0) return ErrorOr<voidPtr>(1); - - auto blockSize = ctx->BlockSize(); - SizeT available = (node->inode.fSize > node->cursor) ? (node->inode.fSize - node->cursor) : 0; - SizeT bytesToRead = (size < available) ? size : available; - if (bytesToRead == 0) return ErrorOr<voidPtr>(2); // nothing to read - - auto buffer = mm_alloc_ptr(bytesToRead, true, false); - if (!buffer) return ErrorOr<voidPtr>(3); // allocation failed - - UInt32 currentOffset = node->cursor; - SizeT remaining = bytesToRead; - UInt8* dest = reinterpret_cast<UInt8*>(buffer); - - while (remaining > 0) { - UInt32 logicalIndex = currentOffset / blockSize; - UInt32 offsetInBlock = currentOffset % blockSize; - - auto phys = ext2_get_block_address(ctx, node, logicalIndex); - if (phys.HasError()) { - mm_free_ptr(buffer); - return ErrorOr<voidPtr>(phys.Error()); - } - - auto blockNumber = phys.Value(); - UInt32 lba = ext2_block_to_lba(ctx, blockNumber); - - auto blockBuf = mm_alloc_ptr(blockSize, true, false); - if (!blockBuf) { - mm_free_ptr(buffer); - return ErrorOr<voidPtr>(4); // block buffer allocation failed - } - - if (!ext2_read_block(ctx->drive, lba, blockBuf, blockSize)) { - mm_free_ptr(blockBuf); - mm_free_ptr(buffer); - return ErrorOr<voidPtr>(5); // block read failed - } - - SizeT chunk = ext2_min(remaining, blockSize - offsetInBlock); - rt_copy_memory_safe(static_cast<void*>(static_cast<UInt8*>(blockBuf) + offsetInBlock), - static_cast<void*>(dest), chunk, chunk); - - mm_free_ptr(blockBuf); - - currentOffset += static_cast<UInt32>(chunk); - dest += chunk; - remaining -= chunk; - } - - node->cursor += static_cast<UInt32>(bytesToRead); - return ErrorOr<voidPtr>(buffer); -} - -// Get group descriptor information for a given block/inode number -static ErrorOr<Ext2GroupInfo*> ext2_get_group_descriptor_info(Ext2Context* ctx, - UInt32 targetBlockOrInode) { - if (!ctx || !ctx->superblock || !ctx->drive) return ErrorOr<Ext2GroupInfo*>(kErrorInvalidData); - - UInt32 blockSize = ctx->BlockSize(); - UInt32 blocksPerGroup = ctx->superblock->fBlocksPerGroup; - UInt32 inodesPerGroup = ctx->superblock->fInodesPerGroup; - UInt32 totalBlocks = ctx->superblock->fBlockCount; - UInt32 totalInodes = ctx->superblock->fInodeCount; - - if (blocksPerGroup == 0 || inodesPerGroup == 0) return ErrorOr<Ext2GroupInfo*>(kErrorInvalidData); - - // block group index - UInt32 groupIndex = 0; - if (targetBlockOrInode == 0) { - groupIndex = 0; - } else if (targetBlockOrInode <= totalInodes) { - // 1-based - groupIndex = (targetBlockOrInode - 1) / inodesPerGroup; - } else { - // EXT2 block number - if (targetBlockOrInode < ctx->superblock->fFirstDataBlock) { - groupIndex = 0; - } else { - groupIndex = (targetBlockOrInode - ctx->superblock->fFirstDataBlock) / blocksPerGroup; - } - } - - // Calculate number of block groups - UInt32 groupsCount = static_cast<UInt32>((totalBlocks + blocksPerGroup - 1) / blocksPerGroup); - if (groupIndex >= groupsCount) return ErrorOr<Ext2GroupInfo*>(kErrorInvalidData); - - // Determine GDT start block - UInt32 gdtStartBlock = - (blockSize == 1024) ? EXT2_GROUP_DESC_BLOCK_SMALL : EXT2_GROUP_DESC_BLOCK_LARGE; - - // Compute byte offset of descriptor within the GDT - const UInt32 descSize = sizeof(EXT2_GROUP_DESCRIPTOR); - UInt64 descByteOffset = static_cast<UInt64>(groupIndex) * descSize; - - // Which EXT2 block contains that descriptor? - UInt32 blockOffsetWithinGdt = static_cast<UInt32>(descByteOffset / blockSize); - UInt32 offsetInGroupDescBlock = static_cast<UInt32>(descByteOffset % blockSize); - UInt32 groupDescriptorBlock = gdtStartBlock + blockOffsetWithinGdt; - - // Allocate buffer and read the block containing the descriptor - auto blockBuffer = mm_alloc_ptr(blockSize, true, false); - if (!blockBuffer) return ErrorOr<Ext2GroupInfo*>(kErrorHeapOutOfMemory); - - UInt32 groupDescriptorLba = ext2_block_to_lba(ctx, groupDescriptorBlock); - if (!ext2_read_block(ctx->drive, groupDescriptorLba, blockBuffer, blockSize)) { - mm_free_ptr(blockBuffer); - return ErrorOr<Ext2GroupInfo*>(kErrorDisk); - } - - auto groupInfo = (Ext2GroupInfo*) mm_alloc_ptr(sizeof(Ext2GroupInfo), true, false); - if (!groupInfo) { - mm_free_ptr(blockBuffer); - return ErrorOr<Ext2GroupInfo*>(kErrorHeapOutOfMemory); - } - - groupInfo->groupDesc = reinterpret_cast<EXT2_GROUP_DESCRIPTOR*>( - reinterpret_cast<UInt8*>(blockBuffer) + offsetInGroupDescBlock); - groupInfo->groupDescriptorBlock = groupDescriptorBlock; - groupInfo->offsetInGroupDescBlock = offsetInGroupDescBlock; - groupInfo->blockBuffer = reinterpret_cast<UInt8*>(blockBuffer); - - return ErrorOr<Ext2GroupInfo*>(groupInfo); -} - -// Allocate a new block -inline ErrorOr<UInt32> ext2_alloc_block(Ext2Context* ctx, EXT2_GROUP_DESCRIPTOR* groupDesc) { - if (!ctx || !ctx->superblock || !groupDesc) return ErrorOr<UInt32>(kErrorInvalidData); - - UInt32 blockSize = ctx->BlockSize(); - - // for the bitmap - auto bitmap = mm_alloc_ptr(blockSize, true, false); - if (!bitmap) return ErrorOr<UInt32>(kErrorHeapOutOfMemory); - - // Read block bitmap - if (!ext2_read_block(ctx->drive, groupDesc->fBlockBitmap, bitmap, blockSize)) { - mm_free_ptr(bitmap); - return ErrorOr<UInt32>(kErrorDisk); - } - - // bit = 0 - for (UInt32 byteIdx = 0; byteIdx < blockSize; ++byteIdx) { - auto byte = reinterpret_cast<unsigned char*>(bitmap)[byteIdx]; - if (byte != 0xFF) { - for (int bit = 0; bit < 8; ++bit) { - if (!(byte & (1 << bit))) { - // Mark bit as used - reinterpret_cast<unsigned char*>(bitmap)[byteIdx] |= (1 << bit); - - // Compute block number - UInt32 blockNumber = byteIdx * 8 + bit; - - // Write bitmap back - if (!ext2_write_block(ctx->drive, groupDesc->fBlockBitmap, bitmap, blockSize)) { - mm_free_ptr(bitmap); - return ErrorOr<UInt32>(kErrorDisk); - } - - // Update group descriptor free count - groupDesc->fFreeBlocksCount--; - mm_free_ptr(bitmap); - return ErrorOr<UInt32>(blockNumber); - } - } - } - } - - mm_free_ptr(bitmap); - return ErrorOr<UInt32>(kErrorDiskIsFull); -} - -// Indirect blocks -static ErrorOr<Void*> ext2_set_block_address(Ext2Context* ctx, Ext2Node* node, - UInt32 logicalBlockIndex, UInt32 physicalBlockNumber) { - using namespace Kernel; - - if (!ctx || !ctx->drive || !node) return ErrorOr<Void*>(kErrorInvalidData); - - auto blockSize = ctx->BlockSize(); - UInt32 blocksPerPointerBlock = blockSize / sizeof(UInt32); - - // Direct blocks - if (logicalBlockIndex < EXT2_DIRECT_BLOCKS) { - node->inode.fBlock[logicalBlockIndex] = physicalBlockNumber; - return ErrorOr<Void*>(nullptr); - } - - // Single indirect blocks - if (logicalBlockIndex < EXT2_DIRECT_BLOCKS + blocksPerPointerBlock) { - if (node->inode.fBlock[EXT2_SINGLE_INDIRECT_INDEX] == 0) { - auto groupInfoRes = ext2_get_group_descriptor_info(ctx, node->inodeNumber); - if (groupInfoRes.HasError()) return ErrorOr<Void*>(groupInfoRes.Error()); - - auto groupInfo = groupInfoRes.Leak().Leak(); // Ref<Ext2GroupInfo*> - auto newBlockRes = ext2_alloc_block(ctx, groupInfo->groupDesc); - if (newBlockRes.HasError()) { - mm_free_ptr(reinterpret_cast<void*>(groupInfo->blockBuffer)); - mm_free_ptr(groupInfo); - return ErrorOr<Void*>(newBlockRes.Error()); - } - - node->inode.fBlock[EXT2_SINGLE_INDIRECT_INDEX] = newBlockRes.Leak(); - - UInt32 gdtLba = ext2_block_to_lba(ctx, groupInfo->groupDescriptorBlock); - if (!ext2_write_block(ctx->drive, gdtLba, groupInfo->blockBuffer, blockSize)) { - mm_free_ptr(reinterpret_cast<void*>(groupInfo->blockBuffer)); - mm_free_ptr(groupInfo); - return ErrorOr<Void*>(kErrorDisk); - } - - mm_free_ptr(reinterpret_cast<void*>(groupInfo->blockBuffer)); - mm_free_ptr(groupInfo); - - // Zero out new indirect block - auto zeroBuf = mm_alloc_ptr(blockSize, true, false); - if (!zeroBuf) return ErrorOr<Void*>(kErrorHeapOutOfMemory); - - rt_zero_memory(zeroBuf, blockSize); - UInt32 indirectLba = ext2_block_to_lba(ctx, node->inode.fBlock[EXT2_SINGLE_INDIRECT_INDEX]); - if (!ext2_write_block(ctx->drive, indirectLba, zeroBuf, blockSize)) { - mm_free_ptr(zeroBuf); - return ErrorOr<Void*>(kErrorDisk); - } - - mm_free_ptr(zeroBuf); - } - - // Read, modify, and write single indirect block - auto indirectRes = ext2_read_block_ptr(ctx, node->inode.fBlock[EXT2_SINGLE_INDIRECT_INDEX]); - if (indirectRes.HasError()) return ErrorOr<Void*>(indirectRes.Error()); - - UInt32* indirectPtr = indirectRes.Leak().Leak(); // Ref<UInt32*> - indirectPtr[logicalBlockIndex - EXT2_DIRECT_BLOCKS] = physicalBlockNumber; - - UInt32 indirectLba = ext2_block_to_lba(ctx, node->inode.fBlock[EXT2_SINGLE_INDIRECT_INDEX]); - if (!ext2_write_block(ctx->drive, indirectLba, indirectPtr, blockSize)) { - mm_free_ptr(indirectPtr); - return ErrorOr<Void*>(kErrorDisk); - } - - mm_free_ptr(indirectPtr); - return ErrorOr<Void*>(nullptr); - } - - // Double - UInt32 doubleStart = EXT2_DIRECT_BLOCKS + blocksPerPointerBlock; - UInt32 doubleSpan = blocksPerPointerBlock * blocksPerPointerBlock; - if (logicalBlockIndex < doubleStart + doubleSpan) { - if (node->inode.fBlock[EXT2_DOUBLE_INDIRECT_INDEX] == 0) { - auto groupInfoRes = ext2_get_group_descriptor_info(ctx, node->inodeNumber); - if (groupInfoRes.HasError()) return ErrorOr<Void*>(groupInfoRes.Error()); - - auto groupInfo = groupInfoRes.Leak().Leak(); - auto newBlockRes = ext2_alloc_block(ctx, groupInfo->groupDesc); - if (newBlockRes.HasError()) { - mm_free_ptr(reinterpret_cast<void*>(groupInfo->blockBuffer)); - mm_free_ptr(groupInfo); - return ErrorOr<Void*>(newBlockRes.Error()); - } - - node->inode.fBlock[EXT2_DOUBLE_INDIRECT_INDEX] = newBlockRes.Leak(); - - UInt32 gdtLba = ext2_block_to_lba(ctx, groupInfo->groupDescriptorBlock); - if (!ext2_write_block(ctx->drive, gdtLba, groupInfo->blockBuffer, blockSize)) { - mm_free_ptr(reinterpret_cast<void*>(groupInfo->blockBuffer)); - mm_free_ptr(groupInfo); - return ErrorOr<Void*>(kErrorDisk); - } - - mm_free_ptr(reinterpret_cast<void*>(groupInfo->blockBuffer)); - mm_free_ptr(groupInfo); - - // Zero new double-indirect block - auto zeroBuf = mm_alloc_ptr(blockSize, true, false); - if (!zeroBuf) return ErrorOr<Void*>(kErrorHeapOutOfMemory); - - rt_zero_memory(zeroBuf, blockSize); - UInt32 dblLba = ext2_block_to_lba(ctx, node->inode.fBlock[EXT2_DOUBLE_INDIRECT_INDEX]); - if (!ext2_write_block(ctx->drive, dblLba, zeroBuf, blockSize)) { - mm_free_ptr(zeroBuf); - return ErrorOr<Void*>(kErrorDisk); - } - - mm_free_ptr(zeroBuf); - } - - // Compute indices - UInt32 idxWithin = logicalBlockIndex - doubleStart; - UInt32 firstIdx = idxWithin / blocksPerPointerBlock; - UInt32 secondIdx = idxWithin % blocksPerPointerBlock; - - auto doubleRes = ext2_read_block_ptr(ctx, node->inode.fBlock[EXT2_DOUBLE_INDIRECT_INDEX]); - if (doubleRes.HasError()) return ErrorOr<Void*>(doubleRes.Error()); - - UInt32* doublePtr = doubleRes.Leak().Leak(); - UInt32 singleIndirectBlock = doublePtr[firstIdx]; - - // Allocate single-indirect if missing - if (singleIndirectBlock == 0) { - auto groupInfoRes = ext2_get_group_descriptor_info(ctx, node->inodeNumber); - if (groupInfoRes.HasError()) { - mm_free_ptr(doublePtr); - return ErrorOr<Void*>(groupInfoRes.Error()); - } - - auto groupInfo = groupInfoRes.Leak().Leak(); - auto newBlockRes = ext2_alloc_block(ctx, groupInfo->groupDesc); - if (newBlockRes.HasError()) { - mm_free_ptr(doublePtr); - mm_free_ptr(reinterpret_cast<void*>(groupInfo->blockBuffer)); - mm_free_ptr(groupInfo); - return ErrorOr<Void*>(newBlockRes.Error()); - } - - singleIndirectBlock = newBlockRes.Leak(); - doublePtr[firstIdx] = singleIndirectBlock; - - // Write back GDT - UInt32 gdtLba = ext2_block_to_lba(ctx, groupInfo->groupDescriptorBlock); - if (!ext2_write_block(ctx->drive, gdtLba, groupInfo->blockBuffer, blockSize)) { - mm_free_ptr(doublePtr); - mm_free_ptr(reinterpret_cast<void*>(groupInfo->blockBuffer)); - mm_free_ptr(groupInfo); - return ErrorOr<Void*>(kErrorDisk); - } - - mm_free_ptr(reinterpret_cast<void*>(groupInfo->blockBuffer)); - mm_free_ptr(groupInfo); - - // Zero single-indirect block - auto zeroBuf = mm_alloc_ptr(blockSize, true, false); - if (!zeroBuf) { - mm_free_ptr(doublePtr); - return ErrorOr<Void*>(kErrorHeapOutOfMemory); - } - - rt_zero_memory(zeroBuf, blockSize); - UInt32 singleLba = ext2_block_to_lba(ctx, singleIndirectBlock); - if (!ext2_write_block(ctx->drive, singleLba, zeroBuf, blockSize)) { - mm_free_ptr(zeroBuf); - mm_free_ptr(doublePtr); - return ErrorOr<Void*>(kErrorDisk); - } - - mm_free_ptr(zeroBuf); - - // Write double-indirect back to disk - UInt32 dblLba = ext2_block_to_lba(ctx, node->inode.fBlock[EXT2_DOUBLE_INDIRECT_INDEX]); - if (!ext2_write_block(ctx->drive, dblLba, doublePtr, blockSize)) { - mm_free_ptr(doublePtr); - return ErrorOr<Void*>(kErrorDisk); - } - } - - mm_free_ptr(doublePtr); - - // Write to single-indirect block - auto singleRes = ext2_read_block_ptr(ctx, singleIndirectBlock); - if (singleRes.HasError()) return ErrorOr<Void*>(singleRes.Error()); - - UInt32* singlePtr = singleRes.Leak().Leak(); - singlePtr[secondIdx] = physicalBlockNumber; - - UInt32 singleLba = ext2_block_to_lba(ctx, singleIndirectBlock); - if (!ext2_write_block(ctx->drive, singleLba, singlePtr, blockSize)) { - mm_free_ptr(singlePtr); - return ErrorOr<Void*>(kErrorDisk); - } - - mm_free_ptr(singlePtr); - return ErrorOr<Void*>(nullptr); - } - - // Triple indirect blocks not implemented - return ErrorOr<Void*>(kErrorUnimplemented); -} - -// Find a directory entry by name within a directory inode -static ErrorOr<EXT2_DIR_ENTRY*> ext2_find_dir_entry(Ext2Context* ctx, Ext2Node* dirNode, - const char* name) { - if (!ctx || !ctx->drive || !dirNode || !name) return ErrorOr<EXT2_DIR_ENTRY*>(kErrorInvalidData); - - // Check directory type - auto type = (dirNode->inode.fMode >> 12) & 0xF; - if (type != kExt2FileTypeDirectory) return ErrorOr<EXT2_DIR_ENTRY*>(kErrorInvalidData); - - UInt32 blockSize = ctx->BlockSize(); - auto blockBuf = mm_alloc_ptr(blockSize, true, false); - if (!blockBuf) return ErrorOr<EXT2_DIR_ENTRY*>(kErrorHeapOutOfMemory); - - SizeT nameLen = rt_string_len(name); - for (UInt32 i = 0; i < EXT2_DIRECT_BLOCKS; ++i) { - UInt32 blockNum = dirNode->inode.fBlock[i]; - if (blockNum == 0) continue; - - UInt32 lba = ext2_block_to_lba(ctx, blockNum); - if (!ext2_read_block(ctx->drive, lba, blockBuf, blockSize)) { - mm_free_ptr(blockBuf); - return ErrorOr<EXT2_DIR_ENTRY*>(kErrorDisk); - } - - UInt32 offset = 0; - while (offset + sizeof(UInt32) + sizeof(UInt16) <= blockSize) { - auto onDiskEntry = reinterpret_cast<EXT2_DIR_ENTRY*>((UInt8*) blockBuf + offset); - if (onDiskEntry->fRecordLength == 0) break; // corrupted - - if (onDiskEntry->fInode != 0 && onDiskEntry->fNameLength == nameLen) { - // Compare names - if (rt_string_cmp(name, onDiskEntry->fName, nameLen) == 0) { - // Allocate a result sized to hold the name + metadata - SizeT recSize = sizeof(EXT2_DIR_ENTRY); - auto found = (EXT2_DIR_ENTRY*) mm_alloc_ptr(recSize, true, false); - if (!found) { - mm_free_ptr(blockBuf); - return ErrorOr<EXT2_DIR_ENTRY*>(kErrorHeapOutOfMemory); - } - - // Copy only record-length bytes - rt_copy_memory_safe(onDiskEntry, found, onDiskEntry->fRecordLength, recSize); - mm_free_ptr(blockBuf); - return ErrorOr<EXT2_DIR_ENTRY*>(found); - } - } - offset += onDiskEntry->fRecordLength; - } - } - - mm_free_ptr(blockBuf); - return ErrorOr<EXT2_DIR_ENTRY*>(kErrorFileNotFound); -} - -// Compute ideal record length for a directory name -static inline UInt16 ext2_dir_entry_ideal_len(UInt8 nameLen) { - UInt16 raw = - static_cast<UInt16>(8 + nameLen); // 8 = inode(4)+rec_len(2)+name_len(1)+file_type(1) - return static_cast<UInt16>((raw + 3) & ~3u); // align up to 4 -} - -static ErrorOr<Void*> ext2_add_dir_entry(Ext2Context* ctx, Ext2Node* parentDirNode, - const char* name, UInt32 inodeNumber, UInt8 fileType) { - using namespace Kernel; - - if (!ctx || !ctx->drive || !parentDirNode || !name) return ErrorOr<Void*>(kErrorInvalidData); - - UInt32 blockSize = ctx->BlockSize(); - SizeT nameLen = rt_string_len(name); - if (nameLen == 0 || nameLen > 255) return ErrorOr<Void*>(kErrorInvalidData); - - UInt16 newRecIdeal = ext2_dir_entry_ideal_len(static_cast<UInt8>(nameLen)); - - auto blockBuf = mm_alloc_ptr(blockSize, true, false); - if (!blockBuf) return ErrorOr<Void*>(kErrorHeapOutOfMemory); - - for (UInt32 bi = 0; bi < EXT2_DIRECT_BLOCKS; ++bi) { - UInt32 blockNum = parentDirNode->inode.fBlock[bi]; - - if (blockNum == 0) { - // Allocate new block - auto groupInfoRes = ext2_get_group_descriptor_info(ctx, parentDirNode->inodeNumber); - if (!groupInfoRes) { - mm_free_ptr(blockBuf); - return ErrorOr<Void*>(groupInfoRes.Error()); - } - - auto groupInfo = *groupInfoRes.Leak(); // Dereference to get Ext2GroupInfo* - auto allocBlockRes = ext2_alloc_block(ctx, groupInfo->groupDesc); - if (!allocBlockRes) { - mm_free_ptr(reinterpret_cast<void*>(groupInfo->blockBuffer)); - mm_free_ptr(groupInfo); - mm_free_ptr(blockBuf); - return ErrorOr<Void*>(allocBlockRes.Error()); - } - - UInt32 newBlock = *allocBlockRes.Leak(); // Dereference to get UInt32 - UInt32 gdtLba = ext2_block_to_lba(ctx, groupInfo->groupDescriptorBlock); - - if (!ext2_write_block(ctx->drive, gdtLba, groupInfo->blockBuffer, blockSize)) { - mm_free_ptr(reinterpret_cast<void*>(groupInfo->blockBuffer)); - mm_free_ptr(groupInfo); - mm_free_ptr(blockBuf); - return ErrorOr<Void*>(kErrorDisk); - } - - mm_free_ptr(reinterpret_cast<void*>(groupInfo->blockBuffer)); - mm_free_ptr(groupInfo); - - // Zero block & insert entry - rt_zero_memory(blockBuf, blockSize); - auto entry = reinterpret_cast<EXT2_DIR_ENTRY*>(blockBuf); - entry->fInode = inodeNumber; - entry->fNameLength = static_cast<UInt8>(nameLen); - entry->fFileType = fileType; - entry->fRecordLength = static_cast<UInt16>(blockSize); - rt_copy_memory_safe(const_cast<char*>(name), entry->fName, nameLen, blockSize); - - UInt32 blockLba = ext2_block_to_lba(ctx, newBlock); - if (!ext2_write_block(ctx->drive, blockLba, blockBuf, blockSize)) { - mm_free_ptr(blockBuf); - return ErrorOr<Void*>(kErrorDisk); - } - - auto setRes = ext2_set_block_address(ctx, parentDirNode, bi, newBlock); - if (!setRes) { - mm_free_ptr(blockBuf); - return ErrorOr<Void*>(setRes.Error()); - } - - mm_free_ptr(blockBuf); - return ErrorOr<Void*>(nullptr); - } - - // read it - UInt32 blockLba = ext2_block_to_lba(ctx, blockNum); - if (!ext2_read_block(ctx->drive, blockLba, blockBuf, blockSize)) { - mm_free_ptr(blockBuf); - return ErrorOr<Void*>(kErrorDisk); - } - - UInt32 offset = 0; - EXT2_DIR_ENTRY* lastEntry = nullptr; - UInt32 lastOffset = 0; - - while (offset < blockSize) { - if (offset + 8 > blockSize) break; - auto e = reinterpret_cast<EXT2_DIR_ENTRY*>((UInt8*) blockBuf + offset); - if (e->fRecordLength == 0) break; - lastEntry = e; - lastOffset = offset; - offset += e->fRecordLength; - } - - if (!lastEntry) continue; - - UInt16 lastIdeal = ext2_dir_entry_ideal_len(lastEntry->fNameLength); - - if (lastEntry->fRecordLength >= (UInt16) (lastIdeal + newRecIdeal)) { - UInt16 origRec = lastEntry->fRecordLength; - lastEntry->fRecordLength = lastIdeal; - - UInt32 newOffset = lastOffset + lastIdeal; - auto newEntry = reinterpret_cast<EXT2_DIR_ENTRY*>((UInt8*) blockBuf + newOffset); - newEntry->fInode = inodeNumber; - newEntry->fNameLength = static_cast<UInt8>(nameLen); - newEntry->fFileType = fileType; - newEntry->fRecordLength = static_cast<UInt16>(origRec - lastIdeal); - rt_copy_memory_safe(const_cast<char*>(name), newEntry->fName, nameLen, - newEntry->fRecordLength); - - if (!ext2_write_block(ctx->drive, blockLba, blockBuf, blockSize)) { - mm_free_ptr(blockBuf); - return ErrorOr<Void*>(kErrorDisk); - } - - mm_free_ptr(blockBuf); - return ErrorOr<Void*>(nullptr); - } - } - - // No space in direct blocks -> allocate new block - int targetIndex = -1; - for (UInt32 i = 0; i < EXT2_DIRECT_BLOCKS; ++i) { - if (parentDirNode->inode.fBlock[i] == 0) { - targetIndex = i; - break; - } - } - if (targetIndex == -1) { - mm_free_ptr(blockBuf); - return ErrorOr<Void*>(kErrorUnimplemented); - } - - auto groupInfoResult = ext2_get_group_descriptor_info(ctx, parentDirNode->inodeNumber); - if (!groupInfoResult) { - mm_free_ptr(blockBuf); - return ErrorOr<Void*>(groupInfoResult.Error()); - } - - auto groupInfo = *groupInfoResult.Leak(); // Dereference to get Ext2GroupInfo* - auto newBlockRes = ext2_alloc_block(ctx, groupInfo->groupDesc); - if (!newBlockRes) { - mm_free_ptr(reinterpret_cast<void*>(groupInfo->blockBuffer)); - mm_free_ptr(groupInfo); - mm_free_ptr(blockBuf); - return ErrorOr<Void*>(newBlockRes.Error()); - } - - UInt32 newBlockNum = *newBlockRes.Leak(); // Dereference to get UInt32 - UInt32 gdtLba = ext2_block_to_lba(ctx, groupInfo->groupDescriptorBlock); - if (!ext2_write_block(ctx->drive, gdtLba, groupInfo->blockBuffer, blockSize)) { - mm_free_ptr(reinterpret_cast<void*>(groupInfo->blockBuffer)); - mm_free_ptr(groupInfo); - mm_free_ptr(blockBuf); - return ErrorOr<Void*>(kErrorDisk); - } - - mm_free_ptr(reinterpret_cast<void*>(groupInfo->blockBuffer)); - mm_free_ptr(groupInfo); - - rt_zero_memory(blockBuf, blockSize); - auto entry = reinterpret_cast<EXT2_DIR_ENTRY*>(blockBuf); - entry->fInode = inodeNumber; - entry->fNameLength = static_cast<UInt8>(nameLen); - entry->fFileType = fileType; - entry->fRecordLength = static_cast<UInt16>(blockSize); - rt_copy_memory_safe(const_cast<char*>(name), entry->fName, nameLen, blockSize); - - UInt32 newBlockLba = ext2_block_to_lba(ctx, newBlockNum); - if (!ext2_write_block(ctx->drive, newBlockLba, blockBuf, blockSize)) { - mm_free_ptr(blockBuf); - return ErrorOr<Void*>(kErrorDisk); - } - - auto setRes = ext2_set_block_address(ctx, parentDirNode, targetIndex, newBlockNum); - if (!setRes) { - mm_free_ptr(blockBuf); - return ErrorOr<Void*>(setRes.Error()); - } - - mm_free_ptr(blockBuf); - return ErrorOr<Void*>(nullptr); -} - -// Soon -static ErrorOr<UInt32> ext2_alloc_inode(Ext2Context* ctx, EXT2_GROUP_DESCRIPTOR* groupDesc) { - if (!ctx || !ctx->superblock || !groupDesc) return ErrorOr<UInt32>(kErrorInvalidData); - - UInt32 blockSize = ctx->BlockSize(); - - // buffer for the inode bitmap - auto bitmap = mm_alloc_ptr(blockSize, true, false); - if (!bitmap) return ErrorOr<UInt32>(kErrorHeapOutOfMemory); - - // Read inode bitmap - if (!ext2_read_block(ctx->drive, groupDesc->fInodeBitmap, bitmap, blockSize)) { - mm_free_ptr(bitmap); - return ErrorOr<UInt32>(kErrorDisk); - } - - // Find first free inode (bit = 0) - for (UInt32 byteIdx = 0; byteIdx < blockSize; ++byteIdx) { - auto byte = reinterpret_cast<unsigned char*>(bitmap)[byteIdx]; - if (byte != 0xFF) { - for (int bit = 0; bit < 8; ++bit) { - if (!(byte & (1 << bit))) { - // Mark bit as used - reinterpret_cast<unsigned char*>(bitmap)[byteIdx] |= (1 << bit); - - // Compute inode number - UInt32 inodeNumber = byteIdx * 8 + bit + 1; // Inodes are 1-based - - // Write bitmap back - if (!ext2_write_block(ctx->drive, groupDesc->fInodeBitmap, bitmap, blockSize)) { - mm_free_ptr(bitmap); - return ErrorOr<UInt32>(kErrorDisk); - } - - // Update group descriptor free count - groupDesc->fFreeInodesCount--; - mm_free_ptr(bitmap); - return ErrorOr<UInt32>(inodeNumber); - } - } - } - } - - mm_free_ptr(bitmap); - return ErrorOr<UInt32>(kErrorDiskIsFull); -} - -// to write an inode to its correct location on disk -static ErrorOr<Void*> ext2_write_inode(Ext2Context* ctx, Ext2Node* node) { - using namespace Kernel; - - if (!ctx || !ctx->superblock || !ctx->drive || !node) return ErrorOr<Void*>(kErrorInvalidData); - - auto blockSize = ctx->BlockSize(); - UInt32 inodesPerGroup = ctx->superblock->fInodesPerGroup; - - if (inodesPerGroup == 0) return ErrorOr<Void*>(kErrorInvalidData); - - // Calculate which group this inode belongs to - UInt32 groupIndex = (node->inodeNumber - 1) / inodesPerGroup; - NE_UNUSED(groupIndex); - UInt32 inodeIndexInGroup = (node->inodeNumber - 1) % inodesPerGroup; - - // Get group descriptor - auto groupInfoResult = ext2_get_group_descriptor_info(ctx, node->inodeNumber); - if (!groupInfoResult) return ErrorOr<Void*>(groupInfoResult.Error()); - - auto groupInfo = *groupInfoResult.Leak(); // Dereference to get Ext2GroupInfo* - - // Calculate inode table position - UInt32 inodeTableBlock = groupInfo->groupDesc->fInodeTable; - UInt32 inodeSize = ctx->superblock->fInodeSize; - UInt32 inodesPerBlock = blockSize / inodeSize; - - UInt32 blockOffset = inodeIndexInGroup / inodesPerBlock; - UInt32 offsetInBlock = (inodeIndexInGroup % inodesPerBlock) * inodeSize; - - UInt32 inodeBlock = inodeTableBlock + blockOffset; - UInt32 inodeLba = ext2_block_to_lba(ctx, inodeBlock); - - // Read the block containing the inode - auto blockBuf = mm_alloc_ptr(blockSize, true, false); - if (!blockBuf) { - mm_free_ptr(reinterpret_cast<void*>(groupInfo->blockBuffer)); - mm_free_ptr(groupInfo); - return ErrorOr<Void*>(kErrorHeapOutOfMemory); - } - - if (!ext2_read_block(ctx->drive, inodeLba, blockBuf, blockSize)) { - mm_free_ptr(blockBuf); - mm_free_ptr(reinterpret_cast<void*>(groupInfo->blockBuffer)); - mm_free_ptr(groupInfo); - return ErrorOr<Void*>(kErrorDisk); - } - - // Copy the updated inode into the block buffer - rt_copy_memory_safe(&node->inode, static_cast<void*>((UInt8*) blockBuf + offsetInBlock), - sizeof(EXT2_INODE), blockSize - offsetInBlock); - - // Write the block back - if (!ext2_write_block(ctx->drive, inodeLba, blockBuf, blockSize)) { - mm_free_ptr(blockBuf); - mm_free_ptr(reinterpret_cast<void*>(groupInfo->blockBuffer)); - mm_free_ptr(groupInfo); - return ErrorOr<Void*>(kErrorDisk); - } - - mm_free_ptr(blockBuf); - mm_free_ptr(reinterpret_cast<void*>(groupInfo->blockBuffer)); - mm_free_ptr(groupInfo); - - return ErrorOr<Void*>(nullptr); -} - -namespace { -// new -struct PathComponents { - const char** components; - int count; - Char* buffer; - - PathComponents(const char* path) : components(nullptr), count(0), buffer(nullptr) { - if (!path || *path == '\0') return; - - SizeT pathLen = rt_string_len(path); - buffer = (Char*) mm_alloc_ptr(pathLen + 1, true, false); - if (!buffer) return; - - rt_copy_memory_safe((void*) path, buffer, pathLen, pathLen + 1); - buffer[pathLen] = '\0'; - - // temp array - const char** temp = (const char**) mm_alloc_ptr(sizeof(char*) * (pathLen + 1), true, false); - if (!temp) { - mm_free_ptr(buffer); - buffer = nullptr; - return; - } - - UInt32 compCount = 0; - Char* p = buffer; - - while (*p != '\0') { - // skip slashes - while (*p == '/') p++; - if (*p == '\0') break; - - Char* start = p; - while (*p != '/' && *p != '\0') p++; - Char saved = *p; - *p = '\0'; - - // handle ".", "..", or normal - if (rt_string_cmp(start, ".", 1) == 0) { - // ignore - } else if (rt_string_cmp(start, "..", 2) == 0) { - if (compCount > 0) compCount--; // go up one level - } else { - temp[compCount++] = start; - } - - *p = saved; - } - - if (compCount == 0) { - mm_free_ptr(temp); - return; - } - - components = (const char**) mm_alloc_ptr(sizeof(char*) * compCount, true, false); - if (!components) { - mm_free_ptr(temp); - return; - } - - for (UInt32 i = 0; i < compCount; i++) components[i] = temp[i]; - count = compCount; - - mm_free_ptr(temp); - } - - ~PathComponents() { - if (components) mm_free_ptr(components); - if (buffer) mm_free_ptr(buffer); - } -}; -} // anonymous namespace - -// The Ext2FileSystemParser (not manager!) -Ext2FileSystemParser::Ext2FileSystemParser(DriveTrait* drive) : fCtx(drive) { - MUST_PASS(fCtx); -} - -NodePtr Ext2FileSystemParser::Open(const char* path, const char* restrict_type) { - NE_UNUSED(restrict_type); - if (!path || *path == '\0' || !this->fCtx.drive) { - return nullptr; - } - - // Root ("/") - if (rt_string_len(path) == 1 && rt_string_cmp(path, "/", 1) == 0) { - auto inodeResult = ext2_load_inode(&this->fCtx, EXT2_ROOT_INODE); - if (!inodeResult) { - return nullptr; - } - - auto heapNode = (Ext2Node*) mm_alloc_ptr(sizeof(Ext2Node), true, false); - if (!heapNode) return nullptr; - - *heapNode = *inodeResult.Leak().Leak(); - heapNode->cursor = 0; - return reinterpret_cast<NodePtr>(heapNode); - } - - PathComponents pathComponents(path); - if (pathComponents.count == 0) { - return nullptr; - } - - UInt32 currentInodeNumber = EXT2_ROOT_INODE; - Ext2Node* currentDirNode = nullptr; - - for (UInt32 i = 0; i < (UInt32) pathComponents.count; ++i) { - auto inodeResult = ext2_load_inode(&this->fCtx, currentInodeNumber); - if (!inodeResult) { - if (currentDirNode) mm_free_ptr(currentDirNode); - return nullptr; - } - - if (currentDirNode) { - mm_free_ptr(currentDirNode); - currentDirNode = nullptr; - } - - currentDirNode = (Ext2Node*) mm_alloc_ptr(sizeof(Ext2Node), true, false); - if (!currentDirNode) { - return nullptr; - } - - *currentDirNode = *inodeResult.Leak().Leak(); - currentDirNode->cursor = 0; - - if (i < pathComponents.count - 1U) { - UInt32 type = (currentDirNode->inode.fMode >> 12) & 0xF; - if (type != kExt2FileTypeDirectory) { - mm_free_ptr(currentDirNode); - return nullptr; - } - } - - auto dirEntryResult = - ext2_find_dir_entry(&this->fCtx, currentDirNode, pathComponents.components[i]); - if (!dirEntryResult) { - mm_free_ptr(currentDirNode); - return nullptr; - } - - EXT2_DIR_ENTRY* entryPtr = *dirEntryResult.Leak(); - currentInodeNumber = entryPtr->fInode; - mm_free_ptr(entryPtr); - } - - auto finalInodeResult = ext2_load_inode(&this->fCtx, currentInodeNumber); - if (!finalInodeResult) { - if (currentDirNode) mm_free_ptr(currentDirNode); - return nullptr; - } - - if (currentDirNode) { - mm_free_ptr(currentDirNode); - } - - auto resultNode = (Ext2Node*) mm_alloc_ptr(sizeof(Ext2Node), true, false); - if (!resultNode) { - return nullptr; - } - - *resultNode = *finalInodeResult.Leak().Leak(); - resultNode->cursor = 0; - return reinterpret_cast<NodePtr>(resultNode); -} - -void* Ext2FileSystemParser::Read(NodePtr node, Int32 flags, SizeT size) { - if (!node) return nullptr; - - NE_UNUSED(flags); - - auto extNode = reinterpret_cast<Ext2Node*>(node); - auto dataResult = ext2_read_inode_data(&this->fCtx, extNode, size); - - if (!dataResult) { - return nullptr; // error, nothing to return - } - - void* data = *dataResult.Leak(); - if (data) { - extNode->cursor += static_cast<UInt32>(size); - } - - return data; -} - -void Ext2FileSystemParser::Write(NodePtr node, void* data, Int32 flags, SizeT size) { - if (!node || !data || size == 0) return; - - NE_UNUSED(flags); - - auto extNode = reinterpret_cast<Ext2Node*>(node); - auto blockSize = this->fCtx.BlockSize(); - SizeT bytesWritten = 0; - - UInt32 currentOffset = extNode->cursor; - UInt8* src = reinterpret_cast<UInt8*>(data); - - while (bytesWritten < size) { - UInt32 logicalBlockIndex = currentOffset / blockSize; - UInt32 offsetInBlock = currentOffset % blockSize; - - auto physBlockResult = ext2_get_block_address(&this->fCtx, extNode, logicalBlockIndex); - UInt32 physicalBlock = 0; - - if (!physBlockResult) { - auto err = physBlockResult.Error(); - if (err == kErrorInvalidData || err == kErrorUnimplemented) { - auto groupInfoResult = ext2_get_group_descriptor_info(&this->fCtx, extNode->inodeNumber); - if (!groupInfoResult) { - return; - } - - auto groupInfo = *groupInfoResult.Leak(); - auto allocResult = ext2_alloc_block(&this->fCtx, groupInfo->groupDesc); - if (!allocResult) { - mm_free_ptr(reinterpret_cast<void*>(groupInfo->blockBuffer)); - mm_free_ptr(groupInfo); - return; - } - - physicalBlock = *allocResult.Leak(); - - auto setRes = - ext2_set_block_address(&this->fCtx, extNode, logicalBlockIndex, physicalBlock); - if (!setRes) { - mm_free_ptr(reinterpret_cast<void*>(groupInfo->blockBuffer)); - mm_free_ptr(groupInfo); - return; - } - - UInt32 gdtLba = ext2_block_to_lba(&this->fCtx, groupInfo->groupDescriptorBlock); - if (!ext2_write_block(this->fCtx.drive, gdtLba, groupInfo->blockBuffer, blockSize)) { - mm_free_ptr(reinterpret_cast<void*>(groupInfo->blockBuffer)); - mm_free_ptr(groupInfo); - return; - } - - mm_free_ptr(reinterpret_cast<void*>(groupInfo->blockBuffer)); - mm_free_ptr(groupInfo); - } else { - return; - } - } else { - physicalBlock = physBlockResult.Value(); - } - - UInt32 physicalLba = ext2_block_to_lba(&this->fCtx, physicalBlock); - - auto blockBuf = mm_alloc_ptr(blockSize, true, false); - if (!blockBuf) return; - - if (offsetInBlock > 0 || (size - bytesWritten) < blockSize) { - if (!ext2_read_block(this->fCtx.drive, physicalLba, blockBuf, blockSize)) { - mm_free_ptr(blockBuf); - return; - } - } else { - rt_zero_memory(blockBuf, blockSize); - } - - UInt32 bytesInCurrentBlock = - static_cast<UInt32>(ext2_min(size - bytesWritten, blockSize - offsetInBlock)); - rt_copy_memory_safe(src, static_cast<void*>((UInt8*) blockBuf + offsetInBlock), - bytesInCurrentBlock, blockSize - offsetInBlock); - - if (!ext2_write_block(this->fCtx.drive, physicalLba, blockBuf, blockSize)) { - mm_free_ptr(blockBuf); - return; - } - - mm_free_ptr(blockBuf); - - currentOffset += bytesInCurrentBlock; - src += bytesInCurrentBlock; - bytesWritten += bytesInCurrentBlock; - } - - if (currentOffset > extNode->inode.fSize) { - extNode->inode.fSize = currentOffset; - } - - extNode->inode.fBlocks = (extNode->inode.fSize + blockSize - 1) / blockSize; - extNode->inode.fModifyTime = 0; - - auto writeInodeRes = ext2_write_inode(&this->fCtx, extNode); - if (!writeInodeRes) { - // Failed to persist inode - } - - extNode->cursor = currentOffset; -} - -bool Ext2FileSystemParser::Seek(NodePtr node, SizeT offset) { - if (!node) return false; - auto extNode = reinterpret_cast<Ext2Node*>(node); - extNode->cursor = static_cast<UInt32>(offset); - return true; -} - -SizeT Ext2FileSystemParser::Tell(NodePtr node) { - if (!node) return 0; - auto extNode = reinterpret_cast<Ext2Node*>(node); - return extNode->cursor; -} - -bool Ext2FileSystemParser::Rewind(NodePtr node) { - if (!node) return false; - auto extNode = reinterpret_cast<Ext2Node*>(node); - extNode->cursor = 0; - return true; -} - -void* Ext2FileSystemParser::Read(const char* name, NodePtr node, Int32 flags, SizeT size) { - NE_UNUSED(name); - return Read(node, flags, size); -} - -void Ext2FileSystemParser::Write(const char* name, NodePtr node, void* data, Int32 flags, - SizeT size) { - NE_UNUSED(name); - Write(node, data, flags, size); -} - -NodePtr Ext2FileSystemParser::Create(const char* path) { - if (!path || *path == '\0') return nullptr; - - PathComponents pathComponents(path); - if (pathComponents.count == 0) return nullptr; - - const char* filename = pathComponents.components[pathComponents.count - 1]; - if (rt_string_len(filename) > kExt2FSMaxFileNameLen) return nullptr; - - // Build parent path - Char parentPathBuf[256] = {0}; - SizeT currentPathLen = 0; - for (UInt32 i = 0; (i < pathComponents.count - 1U); ++i) { - SizeT componentLen = rt_string_len(pathComponents.components[i]); - if (currentPathLen + componentLen + 1 >= sizeof(parentPathBuf)) return nullptr; - if (i > 0) parentPathBuf[currentPathLen++] = '/'; - rt_copy_memory_safe(const_cast<char*>(pathComponents.components[i]), - parentPathBuf + currentPathLen, componentLen, - sizeof(parentPathBuf) - currentPathLen); - currentPathLen += componentLen; - } - parentPathBuf[currentPathLen] = '\0'; - - // Open parent directory - NodePtr parentDirNodePtr = nullptr; - if (currentPathLen == 0) { - // root - auto inodeRes = ext2_load_inode(&this->fCtx, EXT2_ROOT_INODE); - if (!inodeRes) return nullptr; - parentDirNodePtr = mm_alloc_ptr(sizeof(Ext2Node), true, false); - if (!parentDirNodePtr) return nullptr; - *reinterpret_cast<Ext2Node*>(parentDirNodePtr) = *inodeRes.Leak().Leak(); - reinterpret_cast<Ext2Node*>(parentDirNodePtr)->cursor = 0; - } else { - parentDirNodePtr = Open(parentPathBuf, "r"); - } - - if (!parentDirNodePtr) return nullptr; - - auto parentDirNode = reinterpret_cast<Ext2Node*>(parentDirNodePtr); - - // Ensure parent is a directory - UInt32 type = (parentDirNode->inode.fMode >> 12) & 0xF; - if (type != kExt2FileTypeDirectory) { - mm_free_ptr(parentDirNode); - return nullptr; - } - - // Get group info for allocation - auto groupInfoResult = ext2_get_group_descriptor_info(&this->fCtx, parentDirNode->inodeNumber); - if (!groupInfoResult) { - mm_free_ptr(parentDirNode); - return nullptr; - } - auto groupInfo = *groupInfoResult.Leak(); - - // Allocate new inode - auto newInodeRes = ext2_alloc_inode(&this->fCtx, groupInfo->groupDesc); - if (!newInodeRes) { - mm_free_ptr(reinterpret_cast<void*>(groupInfo->blockBuffer)); - mm_free_ptr(groupInfo); // so this works - mm_free_ptr(parentDirNode); - return nullptr; - } - UInt32 newInodeNumber = newInodeRes.Value(); - - UInt32 gdtLba = ext2_block_to_lba(&this->fCtx, groupInfo->groupDescriptorBlock); - if (!ext2_write_block(this->fCtx.drive, gdtLba, groupInfo->blockBuffer, this->fCtx.BlockSize())) { - mm_free_ptr(reinterpret_cast<void*>(groupInfo->blockBuffer)); - mm_free_ptr(groupInfo); - mm_free_ptr(parentDirNode); - return nullptr; - } - - mm_free_ptr(reinterpret_cast<void*>(groupInfo->blockBuffer)); - mm_free_ptr(groupInfo); - - // Create new Ext2Node - Ext2Node* newFileNode = reinterpret_cast<Ext2Node*>(mm_alloc_ptr(sizeof(Ext2Node), true, false)); - if (!newFileNode) { - mm_free_ptr(parentDirNode); - return nullptr; - } - - newFileNode->inodeNumber = newInodeNumber; - rt_zero_memory(&newFileNode->inode, sizeof(EXT2_INODE)); - - newFileNode->inode.fMode = (kExt2FileTypeRegular << 12); - newFileNode->inode.fUID = 0; - newFileNode->inode.fGID = 0; - newFileNode->inode.fLinksCount = 1; - newFileNode->inode.fSize = 0; - newFileNode->inode.fBlocks = 0; - newFileNode->inode.fCreateTime = 0; - newFileNode->inode.fModifyTime = 0; - - // Persist new inode - auto writeInodeRes = ext2_write_inode(&this->fCtx, newFileNode); - if (!writeInodeRes) { - mm_free_ptr(parentDirNode); - mm_free_ptr(newFileNode); - return nullptr; - } - - // Add directory entry - auto addRes = ext2_add_dir_entry(&this->fCtx, parentDirNode, filename, newInodeNumber, - kExt2FileTypeRegular); - if (!addRes) { - mm_free_ptr(parentDirNode); - mm_free_ptr(newFileNode); - return nullptr; - } - - // Update parent inode - auto parentWriteRes = ext2_write_inode(&this->fCtx, parentDirNode); - // ignore failure - - NE_UNUSED(parentWriteRes); - - mm_free_ptr(parentDirNode); - return reinterpret_cast<NodePtr>(newFileNode); -} - -NodePtr Ext2FileSystemParser::CreateDirectory(const char* path) { - if (!path || *path == '\0') return nullptr; - - PathComponents pathComponents(path); - if (pathComponents.count == 0) { - kout << "EXT2: Failed to parse path for CreateDirectory.\n"; - return nullptr; - } - - const char* dirname = pathComponents.components[pathComponents.count - 1]; - if (rt_string_len(dirname) > kExt2FSMaxFileNameLen) { - kout << "EXT2: Directory name too long: " << dirname << ".\n"; - return nullptr; - } - - // Build parent path - Char parentPathBuf[256]; - SizeT currentPathLen = 0; - for (UInt32 i = 0; (i < pathComponents.count - 1U); ++i) { - SizeT componentLen = rt_string_len(pathComponents.components[i]); - if (currentPathLen + componentLen + 1 >= sizeof(parentPathBuf)) { - kout << "EXT2: Parent path too long for CreateDirectory.\n"; - return nullptr; - } - - if (i > 0) parentPathBuf[currentPathLen++] = '/'; - - rt_copy_memory_safe(static_cast<void*>(const_cast<char*>(pathComponents.components[i])), - static_cast<void*>(parentPathBuf + currentPathLen), componentLen, - sizeof(parentPathBuf) - currentPathLen); - currentPathLen += componentLen; - } - - parentPathBuf[currentPathLen] = '\0'; - - // Open parent directory node - NodePtr parentDirNodePtr = nullptr; - if (currentPathLen == 0) { - auto inodeRes = ext2_load_inode(&this->fCtx, EXT2_ROOT_INODE); - if (!inodeRes) { - return nullptr; - } - - parentDirNodePtr = reinterpret_cast<NodePtr>(mm_alloc_ptr(sizeof(Ext2Node), true, false)); - if (!parentDirNodePtr) return nullptr; - - *reinterpret_cast<Ext2Node*>(parentDirNodePtr) = *inodeRes.Leak().Leak(); - reinterpret_cast<Ext2Node*>(parentDirNodePtr)->cursor = 0; - } else { - parentDirNodePtr = Open(parentPathBuf, "r"); - } - - if (!parentDirNodePtr) { - kout << "EXT2: Failed to open parent directory for CreateDirectory: " << parentPathBuf << ".\n"; - return nullptr; - } - - auto parentDirNode = reinterpret_cast<Ext2Node*>(parentDirNodePtr); - - // Check parent is a directory - UInt32 parentType = (parentDirNode->inode.fMode >> 12) & 0xF; - if (parentType != kExt2FileTypeDirectory) { - kout << "EXT2: Parent is not a directory: " << parentPathBuf << ".\n"; - mm_free_ptr(parentDirNode); - return nullptr; - } - - // Allocate inode - auto groupInfoResult = ext2_get_group_descriptor_info(&this->fCtx, parentDirNode->inodeNumber); - if (!groupInfoResult) { - kout << "EXT2: Failed to get group descriptor info for new dir inode.\n"; - mm_free_ptr(parentDirNode); - return nullptr; - } - - auto groupInfo = *groupInfoResult.Leak(); - auto newInodeRes = ext2_alloc_inode(&this->fCtx, groupInfo->groupDesc); - if (!newInodeRes) { - kout << "EXT2: Failed to allocate inode for new directory.\n"; - mm_free_ptr(reinterpret_cast<void*>(groupInfo->blockBuffer)); - mm_free_ptr(groupInfo); - mm_free_ptr(parentDirNode); - return nullptr; - } - - UInt32 newInodeNumber = *newInodeRes.Leak(); - - // Write back group descriptor block - UInt32 gdtLba = ext2_block_to_lba(&this->fCtx, groupInfo->groupDescriptorBlock); - if (!ext2_write_block(this->fCtx.drive, gdtLba, groupInfo->blockBuffer, this->fCtx.BlockSize())) { - kout << "EXT2: Failed to write group descriptor after inode allocation.\n"; - mm_free_ptr(reinterpret_cast<void*>(groupInfo->blockBuffer)); - mm_free_ptr(groupInfo); - mm_free_ptr(parentDirNode); - return nullptr; - } - - mm_free_ptr(reinterpret_cast<void*>(groupInfo->blockBuffer)); - mm_free_ptr(groupInfo); - - // Create new Ext2Node and initialize inode fields - Ext2Node* newDirNode = reinterpret_cast<Ext2Node*>(mm_alloc_ptr(sizeof(Ext2Node), true, false)); - if (!newDirNode) { - kout << "EXT2: Out of memory for new directory node.\n"; - mm_free_ptr(parentDirNode); - return nullptr; - } - - newDirNode->inodeNumber = newInodeNumber; - rt_zero_memory(&newDirNode->inode, sizeof(EXT2_INODE)); - newDirNode->inode.fMode = (kExt2FileTypeDirectory << 12); - newDirNode->inode.fUID = 0; - newDirNode->inode.fGID = 0; - newDirNode->inode.fLinksCount = 2; // . and .. - newDirNode->inode.fSize = this->fCtx.BlockSize(); - newDirNode->inode.fBlocks = 1; - newDirNode->inode.fCreateTime = 0; - newDirNode->inode.fModifyTime = 0; - - // Allocate a data block for the new directory - auto groupForBlockRes = ext2_get_group_descriptor_info(&this->fCtx, newDirNode->inodeNumber); - if (!groupForBlockRes) { - kout << "EXT2: Failed to get group info for directory block allocation.\n"; - mm_free_ptr(parentDirNode); - mm_free_ptr(newDirNode); - return nullptr; - } - - auto groupForBlock = *groupForBlockRes.Leak(); - auto newBlockRes = ext2_alloc_block(&this->fCtx, groupForBlock->groupDesc); - if (!newBlockRes) { - kout << "EXT2: Failed to allocate block for new directory contents.\n"; - mm_free_ptr(reinterpret_cast<void*>(groupForBlock->blockBuffer)); - mm_free_ptr(groupForBlock); - mm_free_ptr(parentDirNode); - mm_free_ptr(newDirNode); - return nullptr; - } - - UInt32 newDirBlockNum = *newBlockRes.Leak(); - - // Write back GDT - UInt32 gdtLba2 = ext2_block_to_lba(&this->fCtx, groupForBlock->groupDescriptorBlock); - if (!ext2_write_block(this->fCtx.drive, gdtLba2, groupForBlock->blockBuffer, - this->fCtx.BlockSize())) { - kout << "EXT2: Failed to write GDT after directory block allocation.\n"; - mm_free_ptr(reinterpret_cast<void*>(groupForBlock->blockBuffer)); - mm_free_ptr(groupForBlock); - mm_free_ptr(parentDirNode); - mm_free_ptr(newDirNode); - return nullptr; - } - - mm_free_ptr(reinterpret_cast<void*>(groupForBlock->blockBuffer)); - mm_free_ptr(groupForBlock); - - // Set the block in newDirNode - auto setBlkRes = ext2_set_block_address(&this->fCtx, newDirNode, 0, newDirBlockNum); - if (!setBlkRes) { - kout << "EXT2: Failed to set data block for new directory.\n"; - mm_free_ptr(parentDirNode); - mm_free_ptr(newDirNode); - return nullptr; - } - - // Prepare block with '.' and '..' - auto dirBlockBuf = mm_alloc_ptr(this->fCtx.BlockSize(), true, false); - if (!dirBlockBuf) { - kout << "EXT2: Out of memory preparing directory block.\n"; - mm_free_ptr(parentDirNode); - mm_free_ptr(newDirNode); - return nullptr; - } - - rt_zero_memory(dirBlockBuf, this->fCtx.BlockSize()); - - // '.' entry - auto dot = reinterpret_cast<EXT2_DIR_ENTRY*>(dirBlockBuf); - dot->fInode = newInodeNumber; - dot->fNameLength = 1; - dot->fFileType = kExt2FileTypeDirectory; - dot->fRecordLength = ext2_dir_entry_ideal_len(dot->fNameLength); - dot->fName[0] = '.'; - - // '..' entry occupies rest of block - auto dotdot = reinterpret_cast<EXT2_DIR_ENTRY*>((UInt8*) dirBlockBuf + dot->fRecordLength); - dotdot->fInode = parentDirNode->inodeNumber; - dotdot->fNameLength = 2; - dotdot->fFileType = kExt2FileTypeDirectory; - dotdot->fRecordLength = static_cast<UInt16>(this->fCtx.BlockSize() - dot->fRecordLength); - dotdot->fName[0] = '.'; - dotdot->fName[1] = '.'; - - // Write dir block to disk - UInt32 newDirBlockLba = ext2_block_to_lba(&this->fCtx, newDirBlockNum); - if (!ext2_write_block(this->fCtx.drive, newDirBlockLba, dirBlockBuf, this->fCtx.BlockSize())) { - kout << "EXT2: Failed to write directory block to disk.\n"; - mm_free_ptr(dirBlockBuf); - mm_free_ptr(parentDirNode); - mm_free_ptr(newDirNode); - return nullptr; - } - - mm_free_ptr(dirBlockBuf); - - // Persist new directory inode - auto writeInodeRes = ext2_write_inode(&this->fCtx, newDirNode); - if (!writeInodeRes) { - kout << "EXT2: Failed to write new directory inode to disk.\n"; - mm_free_ptr(parentDirNode); - mm_free_ptr(newDirNode); - return nullptr; - } - - // Add directory entry into parent - auto addRes = ext2_add_dir_entry(&this->fCtx, parentDirNode, dirname, newInodeNumber, - kExt2FileTypeDirectory); - if (!addRes) { - kout << "EXT2: Failed to add directory entry for '" << dirname << "' to parent.\n"; - mm_free_ptr(parentDirNode); - mm_free_ptr(newDirNode); - return nullptr; - } - - // Increment parent link count and persist parent inode - parentDirNode->inode.fLinksCount += 1; - auto parentWriteRes = ext2_write_inode(&this->fCtx, parentDirNode); - if (!parentWriteRes) { - kout << "EXT2: Warning: failed to update parent inode after directory creation.\n"; - } - - mm_free_ptr(parentDirNode); - return reinterpret_cast<NodePtr>(newDirNode); -} - -#endif -#endif diff --git a/dev/kernel/src/FS/NeFS+FileMgr.cc b/dev/kernel/src/FS/NeFS+FileMgr.cc deleted file mode 100644 index 0fdabd6f..00000000 --- a/dev/kernel/src/FS/NeFS+FileMgr.cc +++ /dev/null @@ -1,276 +0,0 @@ -/* ======================================== - - Copyright (C) 2024-2025, Amlal El Mahrouss, licensed under the Apache 2.0 license. - -======================================== */ - -#ifndef __NE_MINIMAL_OS__ -#ifdef __FSKIT_INCLUDES_NEFS__ - -#include <KernelKit/FileMgr.h> -#include <KernelKit/HeapMgr.h> - -/// @brief NeFS File System Manager. -/// BUGS: 0 - -namespace Kernel { -static inline bool is_valid_nefs_catalog(NodePtr node); - -/// @brief C++ constructor -NeFileSystemMgr::NeFileSystemMgr() { - mParser = new NeFileSystemParser(); - MUST_PASS(mParser); - - kout << "We are done allocating NeFileSystemParser...\n"; -} - -NeFileSystemMgr::~NeFileSystemMgr() { - if (mParser) { - kout << "Destroying NeFileSystemParser...\n"; - delete mParser; - mParser = nullptr; - } -} - -/// @brief Removes a node from the filesystem. -/// @param path The filename -/// @return If it was deleted or not. -bool NeFileSystemMgr::Remove(_Input const Char* path) { - if (path == nullptr || *path == 0) { - kout << "NeFS: Remove called with null or empty path\n"; - return false; - } - return mParser->RemoveCatalog(path); -} - -/// @brief Creates a node with the specified. -/// @param path The filename path. -/// @return The Node pointer. -NodePtr NeFileSystemMgr::Create(_Input const Char* path) { - if (!path || *path == 0) { - kout << "NeFS: Create called with null or empty path\n"; - return nullptr; - } - return rtl_node_cast(mParser->CreateCatalog(path)); -} - -/// @brief Creates a node which is a directory. -/// @param path The filename path. -/// @return The Node pointer. -NodePtr NeFileSystemMgr::CreateDirectory(const Char* path) { - if (!path || *path == 0) { - kout << "NeFS: CreateDirectory called with null or empty path\n"; - return nullptr; - } - return rtl_node_cast(mParser->CreateCatalog(path, 0, kNeFSCatalogKindDir)); -} - -/// @brief Creates a node which is an alias. -/// @param path The filename path. -/// @return The Node pointer. -NodePtr NeFileSystemMgr::CreateAlias(const Char* path) { - if (!path || *path == 0) { - kout << "NeFS: CreateAlias called with null or empty path\n"; - return nullptr; - } - return rtl_node_cast(mParser->CreateCatalog(path, 0, kNeFSCatalogKindAlias)); -} - -NodePtr NeFileSystemMgr::CreateSwapFile(const Char* path) { - if (!path || *path == 0) { - kout << "NeFS: CreateSwapFile called with null or empty path\n"; - return nullptr; - } - return rtl_node_cast(mParser->CreateCatalog(path, 0, kNeFSCatalogKindPage)); -} - -/// @brief Gets the root directory. -/// @return -const Char* NeFileSystemHelper::Root() { - return kNeFSRoot; -} - -/// @brief Gets the up-dir directory. -/// @return -const Char* NeFileSystemHelper::UpDir() { - return kNeFSUpDir; -} - -/// @brief Gets the separator character. -/// @return -Char NeFileSystemHelper::Separator() { - return kNeFSSeparator; -} - -/// @brief Gets the metafile character. -/// @return -Char NeFileSystemHelper::MetaFile() { - return kNeFSMetaFilePrefix; -} - -/// @brief Opens a new file. -/// @param path -/// @param r -/// @return -_Output NodePtr NeFileSystemMgr::Open(_Input const Char* path, _Input const Char* r) { - if (!path || *path == 0) { - kout << "NeFS: Open called with null or empty path\n"; - return nullptr; - } - if (!r || *r == 0) { - kout << "NeFS: Open called with null or empty mode string\n"; - return nullptr; - } - auto catalog = mParser->GetCatalog(path); - if (!catalog) { - kout << "NeFS: Open could not find catalog for path\n"; - return nullptr; - } - return rtl_node_cast(catalog); -} - -Void NeFileSystemMgr::Write(_Input NodePtr node, _Input VoidPtr data, _Input Int32 flags, - _Input SizeT size) { - if (!is_valid_nefs_catalog(node)) { - kout << "NeFS: Write called with invalid node pointer\n"; - return; - } - if (!data) { - kout << "NeFS: Write called with null data pointer\n"; - return; - } - if (!size || size > kNeFSForkSize) { - (Void)(kout << "NeFS: Write called with invalid size: " << hex_number(size)); - kout << "\n"; - return; - } - constexpr auto kDataForkName = kNeFSDataFork; - this->Write(kDataForkName, node, data, flags, size); -} - -_Output VoidPtr NeFileSystemMgr::Read(_Input NodePtr node, _Input Int32 flags, _Input SizeT size) { - if (!is_valid_nefs_catalog(node)) { - kout << "NeFS: Read called with invalid node pointer\n"; - return nullptr; - } - if (!size || size > kNeFSForkSize) { - (Void)(kout << "NeFS: Write called with invalid size: " << hex_number(size)); - kout << "\n"; - return nullptr; - } - constexpr auto kDataForkName = kNeFSDataFork; - return this->Read(kDataForkName, node, flags, size); -} - -Void NeFileSystemMgr::Write(_Input const Char* name, _Input NodePtr node, _Input VoidPtr data, - _Input Int32 flags, _Input SizeT size) { - if (!is_valid_nefs_catalog(node)) { - kout << "NeFS: Write(fork) called with invalid node pointer\n"; - return; - } - if (!name || *name == 0) { - kout << "NeFS: Write(fork) called with null or empty fork name\n"; - return; - } - if (!data) { - kout << "NeFS: Write(fork) called with null data pointer\n"; - return; - } - if (!size || size > kNeFSForkSize) { - (Void)(kout << "NeFS: Write called with invalid size: " << hex_number(size)); - kout << "\n"; - return; - } - NE_UNUSED(flags); - auto cat = reinterpret_cast<NEFS_CATALOG_STRUCT*>(node); - if (cat->Kind == kNeFSCatalogKindFile) { - mParser->WriteCatalog(cat->Name, (flags & kFileFlagRsrc ? true : false), data, size, name); - } -} - -_Output VoidPtr NeFileSystemMgr::Read(_Input const Char* name, _Input NodePtr node, - _Input Int32 flags, _Input SizeT sz) { - if (!is_valid_nefs_catalog(node)) { - kout << "NeFS: Read(fork) called with invalid node pointer\n"; - return nullptr; - } - if (!name || *name == 0) { - kout << "NeFS: Read(fork) called with null or empty fork name\n"; - return nullptr; - } - if (!sz || sz > kNeFSForkSize) { - (Void)(kout << "NeFS: Write called with invalid size: " << hex_number(sz)); - kout << "\n"; - return nullptr; - } - NE_UNUSED(flags); - auto cat = reinterpret_cast<NEFS_CATALOG_STRUCT*>(node); - if (cat->Kind == kNeFSCatalogKindFile) { - return mParser->ReadCatalog(cat, (flags & kFileFlagRsrc ? true : false), sz, name); - } - return nullptr; -} - -_Output Bool NeFileSystemMgr::Seek(NodePtr node, SizeT off) { - if (!is_valid_nefs_catalog(node)) { - kout << "NeFS: Seek called with invalid node pointer\n"; - return false; - } - // Allow off == 0 - return mParser->Seek(reinterpret_cast<NEFS_CATALOG_STRUCT*>(node), off); -} - -/// @brief Tell current offset within catalog. -/// @param node -/// @return kFileMgrNPos if invalid, else current offset. -_Output SizeT NeFileSystemMgr::Tell(NodePtr node) { - if (!is_valid_nefs_catalog(node)) { - kout << "NeFS: Tell called with invalid node pointer\n"; - return kFileMgrNPos; - } - return mParser->Tell(reinterpret_cast<NEFS_CATALOG_STRUCT*>(node)); -} - -/// @brief Rewinds the catalog -/// @param node -/// @return False if invalid, nah? calls Seek(node, 0). -_Output Bool NeFileSystemMgr::Rewind(NodePtr node) { - if (!is_valid_nefs_catalog(node)) { - kout << "NeFS: Rewind called with invalid node pointer\n"; - return false; - } - return this->Seek(node, 0); -} - -/// @brief Returns the parser of NeFS. -_Output NeFileSystemParser* NeFileSystemMgr::GetParser() noexcept { - return mParser; -} - -static inline bool is_valid_nefs_catalog(NodePtr node) { - if (!node) return false; - auto cat = reinterpret_cast<NEFS_CATALOG_STRUCT*>(node); - switch (cat->Kind) { - case kNeFSCatalogKindFile: - case kNeFSCatalogKindDir: - case kNeFSCatalogKindAlias: - case kNeFSCatalogKindPage: - break; - default: - return false; - } - bool null_found = false; - for (int i = 0; i < kNeFSCatalogNameLen; ++i) { - if (cat->Name[i] == 0) { - null_found = true; - break; - } - } - if (!null_found) return false; - return true; -} - -} // namespace Kernel - -#endif // ifdef __FSKIT_INCLUDES_NEFS__ -#endif // ifndef __NE_MINIMAL_OS__ diff --git a/dev/kernel/src/FS/NeFS+FileSystemParser.cc b/dev/kernel/src/FS/NeFS+FileSystemParser.cc deleted file mode 100644 index bfb8d63a..00000000 --- a/dev/kernel/src/FS/NeFS+FileSystemParser.cc +++ /dev/null @@ -1,870 +0,0 @@ -/* ======================================== - - Copyright (C) 2024-2025, Amlal El Mahrouss, licensed under the Apache 2.0 license. - -======================================== */ - -#ifdef __FSKIT_INCLUDES_NEFS__ - -#include <FSKit/NeFS.h> -#include <FirmwareKit/EPM.h> - -#include <KernelKit/DriveMgr.h> -#include <KernelKit/IFS.h> -#include <KernelKit/KPC.h> -#include <KernelKit/ProcessScheduler.h> -#include <KernelKit/UserMgr.h> -#include <NeKit/Crc32.h> -#include <NeKit/KString.h> -#include <NeKit/KernelPanic.h> -#include <NeKit/Utils.h> -#include <modules/AHCI/AHCI.h> -#include <modules/ATA/ATA.h> - -using namespace Kernel; - -#ifdef __NE_NO_BUILTIN__ -/***********************************************************************************/ -/** - Define those external symbols, to make the editor shutup -*/ -/***********************************************************************************/ - -/***********************************************************************************/ -/// @brief get sector count. -/***********************************************************************************/ -Kernel::SizeT drv_std_get_sector_count(); - -/***********************************************************************************/ -/// @brief get device size. -/***********************************************************************************/ -Kernel::SizeT drv_std_get_size(); - -#endif - -///! BUGS: 0 - -/***********************************************************************************/ -/// This file implements the New extended File System. -/// New extended File System implements a flat linked-list based algorithm. -/// / -/// /Path1/ /Path2/ -/// /readme.rtf /ListContents.pef /readme.lnk <-- symlink. -/// /Path1/readme.rtf -/***********************************************************************************/ -static inline bool is_valid_size(SizeT size, SizeT max_size) { - return size > 0 && size <= max_size; -} - -static inline bool is_valid_lba(Lba lba, DriveTrait& drive) { - NEFS_ROOT_PARTITION_BLOCK part_block; - drive.fPacket.fPacketLba = kNeFSRootCatalogStartAddress; - drive.fPacket.fPacketSize = sizeof(NEFS_ROOT_PARTITION_BLOCK); - drive.fPacket.fPacketContent = reinterpret_cast<VoidPtr>(&part_block); - drive.fInput(drive.fPacket); - - if (!drive.fPacket.fPacketGood) { - return false; - } - - // Compute the maximum LBA (DiskSize / sector size) - SizeT sectorSize = drive.fSectorSz; - Lba maxLba = part_block.DiskSize / sectorSize; - - return (lba >= part_block.StartCatalog) && (lba < maxLba); -} - -STATIC IMountpoint kMountpoint; -/***********************************************************************************/ -/// @brief Creates a new fork inside the New filesystem partition. -/// @param catalog it's catalog -/// @param the_fork the fork itself. -/// @return the fork -/***********************************************************************************/ -_Output BOOL NeFileSystemParser::CreateFork(_Input NEFS_FORK_STRUCT& the_fork) { - if (the_fork.ForkName[0] == 0 || the_fork.CatalogName[0] == 0 || the_fork.DataSize == 0) { - return NO; - } - - auto catalog = this->GetCatalog(the_fork.CatalogName); - if (!catalog) return NO; - - Lba lba = catalog->DataFork; - if (lba < kNeFSCatalogStartAddress) { - delete catalog; - return NO; - } - - auto& drv = kMountpoint.A(); - Lba lba_prev = lba; - NEFS_FORK_STRUCT prev_fork{}; - NEFS_FORK_STRUCT cur_fork{}; - - while (true) { - drv.fPacket.fPacketLba = lba; - drv.fPacket.fPacketSize = sizeof(NEFS_FORK_STRUCT); - drv.fPacket.fPacketContent = reinterpret_cast<VoidPtr>(&cur_fork); - drv.fInput(drv.fPacket); - if (!drv.fPacket.fPacketGood) { - delete catalog; - return NO; - } - - if (cur_fork.Flags & kNeFSFlagCreated) { - if (KStringBuilder::Equals(cur_fork.ForkName, the_fork.ForkName) && - KStringBuilder::Equals(cur_fork.CatalogName, the_fork.CatalogName)) { - break; - } - lba_prev = lba; - lba = cur_fork.NextSibling; - prev_fork = cur_fork; - } else { - if (lba >= kNeFSCatalogStartAddress) { - prev_fork.NextSibling = lba; - drv.fPacket.fPacketLba = lba_prev; - drv.fPacket.fPacketSize = sizeof(NEFS_FORK_STRUCT); - drv.fPacket.fPacketContent = reinterpret_cast<VoidPtr>(&prev_fork); - drv.fOutput(drv.fPacket); - } - break; - } - } - - SizeT sectorCount = (the_fork.DataSize + kNeFSSectorSz - 1) / kNeFSSectorSz; - the_fork.DataOffset = lba + 1; - the_fork.PreviousSibling = lba_prev; - the_fork.NextSibling = lba + 1 + sectorCount; - the_fork.Flags |= kNeFSFlagCreated; - - drv.fPacket.fPacketLba = lba; - drv.fPacket.fPacketSize = sizeof(NEFS_FORK_STRUCT); - drv.fPacket.fPacketContent = reinterpret_cast<VoidPtr>(&the_fork); - drv.fOutput(drv.fPacket); - - fs_ifs_write(&kMountpoint, drv, IMountpoint::kDriveIndexA); - - delete catalog; - return YES; -} - -/***********************************************************************************/ -/// @brief Find fork inside filesystem. -/// @param catalog the catalog. -/// @param name the fork name. -/// @return the newly found fork. -/***********************************************************************************/ -_Output NEFS_FORK_STRUCT* NeFileSystemParser::FindFork(_Input NEFS_CATALOG_STRUCT* catalog, - _Input const Char* name, - _Input Boolean is_data) { - if (!catalog || !name) return nullptr; - - auto& drive = kMountpoint.A(); - Lba lba = is_data ? catalog->DataFork : catalog->ResourceFork; - NEFS_FORK_STRUCT local_buf{}; - - while (lba >= kNeFSCatalogStartAddress) { - drive.fPacket.fPacketLba = lba; - drive.fPacket.fPacketSize = sizeof(NEFS_FORK_STRUCT); - drive.fPacket.fPacketContent = reinterpret_cast<VoidPtr>(&local_buf); - - rt_copy_memory_safe((VoidPtr) "fs/nefs-packet", drive.fPacket.fPacketMime, - rt_string_len("fs/nefs-packet"), sizeof(drive.fPacket.fPacketMime)); - - if (auto res = fs_ifs_read(&kMountpoint, drive, this->mDriveIndex); res) { - switch (res) { - case 1: - err_global_get() = kErrorDiskReadOnly; - break; - case 2: - err_global_get() = kErrorDiskIsFull; - break; - case 3: - err_global_get() = kErrorNoSuchDisk; - break; - default: - break; - } - return nullptr; - } - - if (KStringBuilder::Equals(local_buf.ForkName, name) && - KStringBuilder::Equals(local_buf.CatalogName, catalog->Name)) { - auto result = new NEFS_FORK_STRUCT(); - rt_copy_memory_safe(&local_buf, result, sizeof(NEFS_FORK_STRUCT), sizeof(NEFS_FORK_STRUCT)); - return result; - } - - lba = local_buf.NextSibling; - } - - return nullptr; -} - -/***********************************************************************************/ -/// @brief Simpler factory to create a catalog (assumes you want to create a -/// file.) -/// @param name -/// @return catalog pointer. -/***********************************************************************************/ -_Output NEFS_CATALOG_STRUCT* NeFileSystemParser::CreateCatalog(_Input const Char* name) { - return this->CreateCatalog(name, 0, kNeFSCatalogKindFile); -} - -/***********************************************************************************/ -/// @brief Creates a new catalog into the disk. -/// @param name the catalog name. -/// @param flags the flags of the catalog. -/// @param kind the catalog kind. -/// @return catalog pointer. -/***********************************************************************************/ -_Output NEFS_CATALOG_STRUCT* NeFileSystemParser::CreateCatalog(_Input const Char* name, - _Input const Int32& flags, - _Input const Int32& kind) { - kout << "CreateCatalog(*...*)\r"; - - if (!name) return nullptr; - SizeT nameLen = rt_string_len(name); - if (nameLen == 0) return nullptr; - - Lba out_lba = 0UL; - - kout << "Checking for path separator...\r"; - - /// a directory should have a slash in the end. - if (kind == kNeFSCatalogKindDir && name[nameLen - 1] != NeFileSystemHelper::Separator()) - return nullptr; - - /// a file shouldn't have a slash in the end. - if (kind != kNeFSCatalogKindDir && name[nameLen - 1] == NeFileSystemHelper::Separator()) - return nullptr; - - NEFS_CATALOG_STRUCT* catalog_copy = this->FindCatalog(name, out_lba); - - if (catalog_copy) { - kout << "Catalog already exists: " << name << ".\r"; - err_global_get() = kErrorFileExists; - delete catalog_copy; - catalog_copy = nullptr; - return nullptr; - } - - Char* parent_name = (Char*) mm_alloc_ptr(nameLen + 1, Yes, No); - rt_copy_memory_safe(const_cast<Char*>(name), parent_name, nameLen + 1, nameLen + 1); - - if (nameLen < 2) { - mm_free_ptr(parent_name); - err_global_get() = kErrorFileNotFound; - return nullptr; - } - - SizeT index_reverse_copy = nameLen - 1; - if (parent_name[index_reverse_copy] == NeFileSystemHelper::Separator()) { - parent_name[index_reverse_copy] = 0; - --index_reverse_copy; - } - while (index_reverse_copy > 0 && - parent_name[index_reverse_copy] != NeFileSystemHelper::Separator()) { - parent_name[index_reverse_copy] = 0; - --index_reverse_copy; - } - if (index_reverse_copy == 0 && parent_name[0] != NeFileSystemHelper::Separator()) { - mm_free_ptr(parent_name); - err_global_get() = kErrorFileNotFound; - return nullptr; - } - - NEFS_CATALOG_STRUCT* catalog = this->FindCatalog(parent_name, out_lba); - mm_free_ptr(parent_name); - - auto& drive = kMountpoint.A(); - if (catalog && catalog->Kind == kNeFSCatalogKindFile) { - kout << "Parent is a file.\r"; - delete catalog; - return nullptr; - } else if (!catalog) { - Char part_block[sizeof(NEFS_ROOT_PARTITION_BLOCK)] = {0}; - drive.fPacket.fPacketContent = reinterpret_cast<VoidPtr>(part_block); - drive.fPacket.fPacketSize = sizeof(NEFS_ROOT_PARTITION_BLOCK); - drive.fPacket.fPacketLba = kNeFSRootCatalogStartAddress; - drive.fInput(drive.fPacket); - - NEFS_ROOT_PARTITION_BLOCK* blk_nefs = (NEFS_ROOT_PARTITION_BLOCK*) part_block; - out_lba = blk_nefs->StartCatalog; - } - - if (drive.fPacket.fPacketReadOnly) { - delete catalog; - return nullptr; - } - - NEFS_CATALOG_STRUCT* child_catalog = new NEFS_CATALOG_STRUCT(); - child_catalog->Checksum = 0; - child_catalog->ResourceForkSize = 0UL; - child_catalog->DataForkSize = 0UL; - child_catalog->CatalogFlags = kNeFSStatusUnlocked; - child_catalog->NextSibling = out_lba; - child_catalog->PrevSibling = out_lba; - child_catalog->Kind = kind; - child_catalog->Flags |= kNeFSFlagCreated; - child_catalog->CatalogFlags = flags; - - SizeT i = nameLen; - --i; - if (kind == kNeFSCatalogKindDir) --i; - while (name[i] != '/') --i; - rt_copy_memory_safe((VoidPtr) (name + i), (VoidPtr) child_catalog->Name, rt_string_len(name) - i, - kNeFSCatalogNameLen); - - NEFS_CATALOG_STRUCT temporary_catalog{}; - Lba start_free = out_lba; - - rt_copy_memory_safe((VoidPtr) "fs/nefs-packet", drive.fPacket.fPacketMime, - rt_string_len("fs/nefs-packet"), sizeof(drive.fPacket.fPacketMime)); - - Char buf_part_block[sizeof(NEFS_ROOT_PARTITION_BLOCK)] = {0}; - drive.fPacket.fPacketContent = reinterpret_cast<VoidPtr>(buf_part_block); - drive.fPacket.fPacketSize = sizeof(NEFS_ROOT_PARTITION_BLOCK); - drive.fPacket.fPacketLba = kNeFSRootCatalogStartAddress; - drive.fInput(drive.fPacket); - - NEFS_ROOT_PARTITION_BLOCK* part_block = (NEFS_ROOT_PARTITION_BLOCK*) buf_part_block; - drive.fPacket.fPacketContent = reinterpret_cast<VoidPtr>(&temporary_catalog); - drive.fPacket.fPacketSize = sizeof(NEFS_CATALOG_STRUCT); - drive.fPacket.fPacketLba = start_free; - drive.fInput(drive.fPacket); - - if (part_block->FreeCatalog < 1) { - delete child_catalog; - delete catalog; - return nullptr; - } - - kout << "Start finding catalog to allocate or empty space...\r"; - - SizeT catalogSectors = (sizeof(NEFS_CATALOG_STRUCT) + drive.fSectorSz - 1) / drive.fSectorSz; - while (start_free < part_block->StartCatalog + (part_block->CatalogCount * catalogSectors)) { - drive.fPacket.fPacketContent = reinterpret_cast<VoidPtr>(&temporary_catalog); - drive.fPacket.fPacketSize = sizeof(NEFS_CATALOG_STRUCT); - drive.fPacket.fPacketLba = start_free; - drive.fInput(drive.fPacket); - - if ((temporary_catalog.Flags & kNeFSFlagCreated) == 0) { - child_catalog->NextSibling = start_free + catalogSectors; - - NEFS_CATALOG_STRUCT placeholder{}; - drive.fPacket.fPacketContent = reinterpret_cast<VoidPtr>(&placeholder); - drive.fPacket.fPacketSize = sizeof(NEFS_CATALOG_STRUCT); - drive.fPacket.fPacketLba = start_free; - drive.fOutput(drive.fPacket); - - child_catalog->DataFork = part_block->DiskSize - start_free; - child_catalog->ResourceFork = child_catalog->DataFork; - - drive.fPacket.fPacketContent = reinterpret_cast<VoidPtr>(child_catalog); - drive.fPacket.fPacketSize = sizeof(NEFS_CATALOG_STRUCT); - drive.fPacket.fPacketLba = start_free; - drive.fOutput(drive.fPacket); - - drive.fPacket.fPacketContent = reinterpret_cast<VoidPtr>(buf_part_block); - drive.fPacket.fPacketSize = sizeof(NEFS_ROOT_PARTITION_BLOCK); - drive.fPacket.fPacketLba = kNeFSRootCatalogStartAddress; - drive.fInput(drive.fPacket); - - part_block->FreeSectors -= catalogSectors; - part_block->CatalogCount += 1; - part_block->FreeCatalog -= 1; - - drive.fPacket.fPacketContent = reinterpret_cast<VoidPtr>(part_block); - drive.fPacket.fPacketSize = sizeof(NEFS_ROOT_PARTITION_BLOCK); - drive.fPacket.fPacketLba = kNeFSRootCatalogStartAddress; - drive.fOutput(drive.fPacket); - - delete catalog; - NEFS_CATALOG_STRUCT* found_catalog = new NEFS_CATALOG_STRUCT(); - rt_copy_memory_safe(&temporary_catalog, found_catalog, sizeof(NEFS_CATALOG_STRUCT), - sizeof(NEFS_CATALOG_STRUCT)); - - delete child_catalog; - return found_catalog; - } else if ((temporary_catalog.Flags & kNeFSFlagCreated) && - KStringBuilder::Equals(temporary_catalog.Name, name)) { - rt_copy_memory_safe(&temporary_catalog, child_catalog, sizeof(NEFS_CATALOG_STRUCT), - sizeof(NEFS_CATALOG_STRUCT)); - delete catalog; - return child_catalog; - } - - start_free += catalogSectors; - } - - delete child_catalog; - delete catalog; - return nullptr; -} - -/***********************************************************************************/ -/// @brief Make a EPM+NeFS drive out of the disk. -/// @param drive The drive to write on. -/// @return If it was sucessful, see err_global_get(). -/***********************************************************************************/ -bool NeFileSystemParser::Format(_Input _Output DriveTrait* drive, _Input const Int32 flags, - const Char* part_name) { - if (!part_name || *part_name == 0) return false; - NE_UNUSED(flags); - - // verify disk. - drive->fVerify(drive->fPacket); - rt_copy_memory_safe((VoidPtr) "fs/nefs-packet", drive->fPacket.fPacketMime, - rt_string_len("fs/nefs-packet"), sizeof(drive->fPacket.fPacketMime)); - if (!drive->fPacket.fPacketGood) { - err_global_get() = kErrorDiskIsCorrupted; - return false; - } - - Char fs_buf[sizeof(NEFS_ROOT_PARTITION_BLOCK)] = {0}; - Lba start = drive->fLbaStart; - - drive->fPacket.fPacketContent = reinterpret_cast<VoidPtr>(fs_buf); - drive->fPacket.fPacketSize = sizeof(NEFS_ROOT_PARTITION_BLOCK); - drive->fPacket.fPacketLba = start; - drive->fInput(drive->fPacket); - - NEFS_ROOT_PARTITION_BLOCK* part_block = (NEFS_ROOT_PARTITION_BLOCK*) fs_buf; - if (rt_string_cmp(kNeFSIdent, part_block->Ident, kNeFSIdentLen) == 0) return true; - - const auto kNeFSUntitledHD = part_name; - rt_copy_memory_safe((VoidPtr) kNeFSIdent, (VoidPtr) part_block->Ident, kNeFSIdentLen, - sizeof(part_block->Ident)); - rt_copy_memory_safe((VoidPtr) kNeFSUntitledHD, (VoidPtr) part_block->PartitionName, - rt_string_len(kNeFSUntitledHD), sizeof(part_block->PartitionName)); - - SizeT sectorCount = drv_std_get_sector_count(); - SizeT sectorSize = drive->fSectorSz; - SizeT totalBytes = sectorCount * sectorSize; - SizeT catalogEntries = totalBytes / sizeof(NEFS_CATALOG_STRUCT); - SizeT catalogSectors = (sizeof(NEFS_CATALOG_STRUCT) + sectorSize - 1) / sectorSize; - - part_block->Version = kNeFSVersionInteger; - part_block->Kind = kNeFSPartitionTypeStandard; - part_block->StartCatalog = start + catalogSectors; - part_block->Flags = 0UL; - part_block->CatalogCount = catalogEntries; - part_block->FreeCatalog = catalogEntries - 1; - part_block->SectorCount = sectorCount; - part_block->DiskSize = totalBytes; - part_block->SectorSize = sectorSize; - part_block->FreeSectors = sectorCount - catalogSectors; - - drive->fPacket.fPacketContent = reinterpret_cast<VoidPtr>(fs_buf); - drive->fPacket.fPacketSize = sizeof(NEFS_ROOT_PARTITION_BLOCK); - drive->fPacket.fPacketLba = start; - drive->fOutput(drive->fPacket); - - (Void)(kout << "Drive kind: " << drive->fProtocol() << kendl); - (Void)(kout << "Partition name: " << part_block->PartitionName << kendl); - (Void)(kout << "Start catalog: " << hex_number(part_block->StartCatalog) << kendl); - (Void)(kout << "Number of catalogs: " << hex_number(part_block->CatalogCount) << kendl); - (Void)(kout << "Free catalog: " << hex_number(part_block->FreeCatalog) << kendl); - (Void)(kout << "Free sectors: " << hex_number(part_block->FreeSectors) << kendl); - (Void)(kout << "Sector size: " << hex_number(part_block->SectorSize) << kendl); - - return true; -} - -/***********************************************************************************/ -/// @brief Writes the data fork into a specific catalog. -/// @param catalog the catalog itself -/// @param data the data. -/// @return if the catalog wrote the contents successfully. -/***********************************************************************************/ -bool NeFileSystemParser::WriteCatalog(_Input const Char* catalog_name, Bool is_rsrc_fork, - _Input VoidPtr data, _Input SizeT size_of_data, - _Input const Char* fork_name) { - if (size_of_data < 1) return NO; - - auto catalog = this->GetCatalog(catalog_name); - if (!catalog) { - kout << "NeFS: WriteCatalog failed to find catalog: " << catalog_name << "\n"; - return false; - } - - SizeT maxSize = is_rsrc_fork ? catalog->ResourceForkSize : catalog->DataForkSize; - - if (!is_valid_size(size_of_data, maxSize)) { - (Void)(kout << "NeFS: WriteCatalog called with invalid size: " << hex_number(size_of_data)); - kout << "\n"; - - delete catalog; - return false; - } - - Lba startFork = is_rsrc_fork ? catalog->ResourceFork : catalog->DataFork; - auto& drive = kMountpoint.A(); - - if (!is_valid_lba(startFork, drive)) { - (Void)(kout << "NeFS: WriteCatalog called with invalid LBA: " << hex_number(startFork)); - kout << "\n"; - - delete catalog; - return false; - } - - NEFS_ROOT_PARTITION_BLOCK part_block; - drive.fPacket.fPacketLba = kNeFSRootCatalogStartAddress; - drive.fPacket.fPacketSize = sizeof(part_block); - drive.fPacket.fPacketContent = reinterpret_cast<VoidPtr>(&part_block); - drive.fInput(drive.fPacket); - - auto buf = new UInt8[size_of_data]; - rt_set_memory(buf, 0, size_of_data); - rt_copy_memory_safe(data, buf, size_of_data, size_of_data); - rt_copy_memory_safe((VoidPtr) "fs/nefs-packet", drive.fPacket.fPacketMime, - rt_string_len("fs/nefs-packet"), sizeof(drive.fPacket.fPacketMime)); - - NEFS_FORK_STRUCT* fork_data_input = new NEFS_FORK_STRUCT(); - NEFS_FORK_STRUCT prev_fork{}; - - while (startFork >= part_block.StartCatalog && drive.fPacket.fPacketGood) { - drive.fPacket.fPacketContent = reinterpret_cast<VoidPtr>(fork_data_input); - drive.fPacket.fPacketSize = sizeof(NEFS_FORK_STRUCT); - drive.fPacket.fPacketLba = startFork; - drive.fInput(drive.fPacket); - - if (!drive.fPacket.fPacketGood) { - break; - } - - if ((fork_data_input->Flags & kNeFSFlagCreated) && - KStringBuilder::Equals(fork_data_input->ForkName, fork_name) && - KStringBuilder::Equals(fork_data_input->CatalogName, catalog_name) && - fork_data_input->DataSize == size_of_data) { - SizeT bytes_left = size_of_data; - SizeT offset = 0; - Lba base_lba = fork_data_input->DataOffset; - - while (bytes_left > 0) { - SizeT chunk = (bytes_left > kNeFSSectorSz) ? kNeFSSectorSz : bytes_left; - drive.fPacket.fPacketContent = reinterpret_cast<VoidPtr>(buf + offset); - drive.fPacket.fPacketSize = chunk; - drive.fPacket.fPacketLba = base_lba + (offset / kNeFSSectorSz); - drive.fOutput(drive.fPacket); - offset += chunk; - bytes_left -= chunk; - } - - delete fork_data_input; - delete[] buf; - delete catalog; - return true; - } - - prev_fork = *fork_data_input; - startFork = fork_data_input->NextSibling; - } - - delete fork_data_input; - delete[] buf; - delete catalog; - return false; -} - -/***********************************************************************************/ -/// @brief -/// @param catalog_name the catalog name. -/// @return the newly found catalog. -/***********************************************************************************/ -_Output NEFS_CATALOG_STRUCT* NeFileSystemParser::FindCatalog(_Input const Char* catalog_name, - Lba& out_lba, Bool search_hidden, - Bool local_search) { - if (!catalog_name || *catalog_name == 0) return nullptr; - - NEFS_ROOT_PARTITION_BLOCK part{}; - auto& drive = kMountpoint.A(); - - rt_copy_memory_safe((VoidPtr) "fs/nefs-packet", drive.fPacket.fPacketMime, - rt_string_len("fs/nefs-packet"), sizeof(drive.fPacket.fPacketMime)); - drive.fPacket.fPacketContent = reinterpret_cast<VoidPtr>(&part); - drive.fPacket.fPacketSize = sizeof(NEFS_ROOT_PARTITION_BLOCK); - drive.fPacket.fPacketLba = kNeFSRootCatalogStartAddress; - drive.fInput(drive.fPacket); - - auto start_catalog_lba = kNeFSCatalogStartAddress; - - // Helper lambda to scan from a given LBA - auto scan_from = [&](Lba lba_start, Bool allow_hidden) -> NEFS_CATALOG_STRUCT* { - Lba cursor = lba_start; - NEFS_CATALOG_STRUCT tmp{}; - while (cursor >= part.StartCatalog && drive.fPacket.fPacketGood) { - drive.fPacket.fPacketLba = cursor; - drive.fPacket.fPacketContent = reinterpret_cast<VoidPtr>(&tmp); - drive.fPacket.fPacketSize = sizeof(NEFS_CATALOG_STRUCT); - drive.fInput(drive.fPacket); - - if (KStringBuilder::Equals( - tmp.Name, catalog_name + (rt_string_len(catalog_name) - rt_string_len(tmp.Name)))) { - if (tmp.Status == kNeFSStatusLocked && !allow_hidden) { - err_global_get() = kErrorFileLocked; - return nullptr; - } - if (!(tmp.Flags & kNeFSFlagCreated)) { - err_global_get() = kErrorFileNotFound; - return nullptr; - } - NEFS_CATALOG_STRUCT* catalog_ptr = new NEFS_CATALOG_STRUCT(); - rt_copy_memory_safe(&tmp, catalog_ptr, sizeof(NEFS_CATALOG_STRUCT), - sizeof(NEFS_CATALOG_STRUCT)); - out_lba = cursor; - return catalog_ptr; - } - cursor = tmp.NextSibling; - } - return nullptr; - }; - - if (!KStringBuilder::Equals(catalog_name, NeFileSystemHelper::Root()) && local_search) { - Char parent_name[kNeFSCatalogNameLen] = {0}; - SizeT nameLen = rt_string_len(catalog_name); - rt_copy_memory_safe(const_cast<Char*>(catalog_name), parent_name, nameLen + 1, - kNeFSCatalogNameLen); - - SizeT indexReverseCopy = nameLen - 1; - if (parent_name[indexReverseCopy] == NeFileSystemHelper::Separator()) { - parent_name[indexReverseCopy] = 0; - --indexReverseCopy; - } - while (indexReverseCopy > 0 && - parent_name[indexReverseCopy] != NeFileSystemHelper::Separator()) { - parent_name[indexReverseCopy] = 0; - --indexReverseCopy; - } - if (indexReverseCopy == 0 && parent_name[0] != NeFileSystemHelper::Separator()) { - return nullptr; - } - - NEFS_CATALOG_STRUCT* parent_catalog = - this->FindCatalog(parent_name, out_lba, search_hidden, NO); - if (parent_catalog) { - start_catalog_lba = parent_catalog->NextSibling; - delete parent_catalog; - NEFS_CATALOG_STRUCT* found = scan_from(start_catalog_lba, search_hidden); - if (found) return found; - } - } - - return scan_from(part.StartCatalog, search_hidden); -} - -/***********************************************************************************/ -/// @brief Get catalog from filesystem. -/// @param name the catalog's name/ -/// @return -/***********************************************************************************/ -_Output NEFS_CATALOG_STRUCT* NeFileSystemParser::GetCatalog(_Input const Char* name) { - Lba unused = 0; - return this->FindCatalog(name, unused, YES, YES); -} - -/***********************************************************************************/ -/// @brief Closes a catalog, (frees it). -/// @param catalog the catalog to close. -/// @return -/***********************************************************************************/ -_Output Boolean NeFileSystemParser::CloseCatalog(_Input _Output NEFS_CATALOG_STRUCT* catalog) { - if (!catalog) return false; - delete catalog; - catalog = nullptr; - return true; -} - -/***********************************************************************************/ -/// @brief Mark catalog as removed. -/// @param catalog The catalog structure. -/// @return if the catalog was removed or not. -/***********************************************************************************/ -_Output Boolean NeFileSystemParser::RemoveCatalog(_Input const Char* catalog_name) { - if (!catalog_name || KStringBuilder::Equals(catalog_name, NeFileSystemHelper::Root())) { - err_global_get() = kErrorInternal; - return false; - } - - Lba out_lba = 0; - auto catalog = this->FindCatalog(catalog_name, out_lba, YES, YES); - if (!catalog) return false; - - auto& drive = kMountpoint.A(); - NEFS_FORK_STRUCT fork_buf{}; - Lba fork_lba = catalog->DataFork; - while (fork_lba >= kNeFSCatalogStartAddress) { - drive.fPacket.fPacketLba = fork_lba; - drive.fPacket.fPacketSize = sizeof(fork_buf); - drive.fPacket.fPacketContent = reinterpret_cast<VoidPtr>(&fork_buf); - drive.fInput(drive.fPacket); - - fork_buf.Flags &= (~kNeFSFlagCreated); - fork_buf.Flags |= kNeFSFlagDeleted; - - drive.fPacket.fPacketContent = reinterpret_cast<VoidPtr>(&fork_buf); - drive.fPacket.fPacketSize = sizeof(fork_buf); - drive.fPacket.fPacketLba = fork_lba; - drive.fOutput(drive.fPacket); - - fork_lba = fork_buf.NextSibling; - } - - fork_lba = catalog->ResourceFork; - while (fork_lba >= kNeFSCatalogStartAddress) { - drive.fPacket.fPacketLba = fork_lba; - drive.fPacket.fPacketSize = sizeof(fork_buf); - drive.fPacket.fPacketContent = reinterpret_cast<VoidPtr>(&fork_buf); - drive.fInput(drive.fPacket); - - fork_buf.Flags &= (~kNeFSFlagCreated); - fork_buf.Flags |= kNeFSFlagDeleted; - - drive.fPacket.fPacketContent = reinterpret_cast<VoidPtr>(&fork_buf); - drive.fPacket.fPacketSize = sizeof(fork_buf); - drive.fPacket.fPacketLba = fork_lba; - drive.fOutput(drive.fPacket); - - fork_lba = fork_buf.NextSibling; - } - - if (out_lba >= kNeFSCatalogStartAddress || (catalog->Flags & kNeFSFlagCreated)) { - catalog->Flags &= (~kNeFSFlagCreated); - catalog->Flags |= kNeFSFlagDeleted; - - rt_copy_memory_safe((VoidPtr) "fs/nefs-packet", drive.fPacket.fPacketMime, - rt_string_len("fs/nefs-packet"), sizeof(drive.fPacket.fPacketMime)); - drive.fPacket.fPacketLba = out_lba; - drive.fPacket.fPacketSize = sizeof(NEFS_CATALOG_STRUCT); - drive.fPacket.fPacketContent = reinterpret_cast<VoidPtr>(catalog); - drive.fOutput(drive.fPacket); - - Char partitionBlockBuf[sizeof(NEFS_ROOT_PARTITION_BLOCK)] = {0}; - drive.fPacket.fPacketLba = kNeFSRootCatalogStartAddress; - drive.fPacket.fPacketContent = reinterpret_cast<VoidPtr>(partitionBlockBuf); - drive.fPacket.fPacketSize = sizeof(NEFS_ROOT_PARTITION_BLOCK); - drive.fInput(drive.fPacket); - - NEFS_ROOT_PARTITION_BLOCK* part_block = (NEFS_ROOT_PARTITION_BLOCK*) partitionBlockBuf; - if (part_block->CatalogCount > 0) --part_block->CatalogCount; - ++part_block->FreeSectors; - - drive.fPacket.fPacketContent = reinterpret_cast<VoidPtr>(part_block); - drive.fPacket.fPacketSize = sizeof(NEFS_ROOT_PARTITION_BLOCK); - drive.fPacket.fPacketLba = kNeFSRootCatalogStartAddress; - drive.fOutput(drive.fPacket); - - delete catalog; - catalog = nullptr; - return true; - } - - delete catalog; - catalog = nullptr; - return false; -} - -/// ***************************************************************** /// -/// Reading,Seek,Tell are unimplemented on catalogs, refer to forks I/O instead. -/// ***************************************************************** /// - -/***********************************************************************************/ -/// @brief Read the catalog data fork. -/// @param catalog -/// @param dataSz -/// @return -/***********************************************************************************/ -VoidPtr NeFileSystemParser::ReadCatalog(_Input _Output NEFS_CATALOG_STRUCT* catalog, - _Input Bool is_rsrc_fork, _Input SizeT dataSz, - _Input const Char* forkName) { - if (!catalog) { - err_global_get() = kErrorInvalidData; - return nullptr; - } - // Validate size against fork size - SizeT maxSize = is_rsrc_fork ? catalog->ResourceForkSize : catalog->DataForkSize; - if (!is_valid_size(dataSz, maxSize)) { - kout << "NeFS: ReadCatalog called with invalid size: "; - hex_number(dataSz); - kout << "\n"; - return nullptr; - } - - Lba dataForkLba = is_rsrc_fork ? catalog->ResourceFork : catalog->DataFork; - auto& drive = kMountpoint.A(); - if (!is_valid_lba(dataForkLba, drive)) { - kout << "NeFS: ReadCatalog called with invalid LBA: "; - hex_number(dataForkLba); - kout << "\n"; - return nullptr; - } - - auto* fs_buf = new NEFS_FORK_STRUCT(); - rt_copy_memory_safe((VoidPtr) "fs/nefs-packet", drive.fPacket.fPacketMime, - rt_string_len("fs/nefs-packet"), sizeof(drive.fPacket.fPacketMime)); - - NEFS_FORK_STRUCT* fs_fork_data = nullptr; - while (dataForkLba >= kNeFSCatalogStartAddress) { - drive.fPacket.fPacketLba = dataForkLba; - drive.fPacket.fPacketSize = sizeof(NEFS_FORK_STRUCT); - drive.fPacket.fPacketContent = reinterpret_cast<VoidPtr>(fs_buf); - drive.fInput(drive.fPacket); - - fs_fork_data = fs_buf; - (Void)(kout << "ForkName: " << fs_fork_data->ForkName << kendl); - (Void)(kout << "CatalogName: " << fs_fork_data->CatalogName << kendl); - - if (KStringBuilder::Equals(forkName, fs_fork_data->ForkName) && - KStringBuilder::Equals(catalog->Name, fs_fork_data->CatalogName)) { - break; - } - dataForkLba = fs_fork_data->NextSibling; - } - - if (dataForkLba < kNeFSCatalogStartAddress) { - delete fs_buf; - return nullptr; - } - return fs_fork_data; -} - -/***********************************************************************************/ -/// @brief Seek in the data fork. -/// @param catalog the catalog offset. -/// @param off where to seek. -/// @return if the seeking was successful. -/***********************************************************************************/ -bool NeFileSystemParser::Seek(_Input _Output NEFS_CATALOG_STRUCT* catalog, SizeT off) { - NE_UNUSED(catalog); - NE_UNUSED(off); - err_global_get() = kErrorUnimplemented; - return false; -} - -/***********************************************************************************/ -/// @brief Tell where we are inside the data fork. -/// @param catalog -/// @return The position on the file. -/***********************************************************************************/ -SizeT NeFileSystemParser::Tell(_Input _Output NEFS_CATALOG_STRUCT* catalog) { - NE_UNUSED(catalog); - err_global_get() = kErrorUnimplemented; - return 0; -} - -namespace Kernel::NeFS { -/***********************************************************************************/ -/// @brief Construct NeFS drives. -/***********************************************************************************/ -Boolean fs_init_nefs(Void) noexcept { - kout << "Creating OpenHeFS disk...\r"; - kMountpoint.A() = io_construct_main_drive(); - if (kMountpoint.A().fPacket.fPacketReadOnly == YES) - ke_panic(RUNTIME_CHECK_FILESYSTEM, "Main disk cannot be mounted."); - NeFileSystemParser parser; - return parser.Format(&kMountpoint.A(), 0, kNeFSVolumeName); -} -} // namespace Kernel::NeFS - -#endif // ifdef __FSKIT_INCLUDES_NEFS__ diff --git a/dev/kernel/src/FS/OpenHeFS+FileMgr.cc b/dev/kernel/src/FS/OpenHeFS+FileMgr.cc deleted file mode 100644 index e70e3626..00000000 --- a/dev/kernel/src/FS/OpenHeFS+FileMgr.cc +++ /dev/null @@ -1,191 +0,0 @@ -/* ======================================== - - Copyright (C) 2024-2025, Amlal El Mahrouss, licensed under the Apache 2.0 license. - -======================================== */ - -#ifndef __NE_MINIMAL_OS__ -#ifdef __FSKIT_INCLUDES_OPENHEFS__ - -#include <KernelKit/FileMgr.h> -#include <KernelKit/HeapMgr.h> - -/// @brief OpenHeFS File System Manager. -/// BUGS: 0 - -namespace Kernel { -/// @brief C++ constructor -HeFileSystemMgr::HeFileSystemMgr() { - mParser = new HeFileSystemParser(); - MUST_PASS(mParser); - - kout << "We are done allocating HeFileSystemParser...\n"; -} - -HeFileSystemMgr::~HeFileSystemMgr() { - if (mParser) { - kout << "Destroying HeFileSystemParser...\n"; - delete mParser; - mParser = nullptr; - } -} - -/// @brief Removes a node from the filesystem. -/// @param path The filename -/// @return If it was deleted or not. -bool HeFileSystemMgr::Remove(_Input const Char* path) { - if (path == nullptr || *path == 0) { - kout << "OpenHeFS: Remove called with null or empty path\n"; - return false; - } - - return NO; -} - -/// @brief Creates a node with the specified. -/// @param path The filename path. -/// @return The Node pointer. -NodePtr HeFileSystemMgr::Create(_Input const Char* path) { - if (!path || *path == 0) { - kout << "OpenHeFS: Create called with null or empty path\n"; - return nullptr; - } - return nullptr; -} - -/// @brief Creates a node which is a directory. -/// @param path The filename path. -/// @return The Node pointer. -NodePtr HeFileSystemMgr::CreateDirectory(const Char* path) { - if (!path || *path == 0) { - kout << "OpenHeFS: CreateDirectory called with null or empty path\n"; - return nullptr; - } - return nullptr; -} - -/// @brief Creates a node which is an alias. -/// @param path The filename path. -/// @return The Node pointer. -NodePtr HeFileSystemMgr::CreateAlias(const Char* path) { - if (!path || *path == 0) { - kout << "OpenHeFS: CreateAlias called with null or empty path\n"; - return nullptr; - } - return nullptr; -} - -NodePtr HeFileSystemMgr::CreateSwapFile(const Char* path) { - if (!path || *path == 0) { - kout << "OpenHeFS: CreateSwapFile called with null or empty path\n"; - return nullptr; - } - return nullptr; -} - -/// @brief Gets the root directory. -/// @return -const Char* NeFileSystemHelper::Root() { - return kHeFSRootDirectory; -} - -/// @brief Gets the up-dir directory. -/// @return -const Char* NeFileSystemHelper::UpDir() { - return kHeFSUpDir; -} - -/// @brief Gets the separator character. -/// @return -Char NeFileSystemHelper::Separator() { - return kHeFSSeparator; -} - -/// @brief Gets the metafile character. -/// @return -Char NeFileSystemHelper::MetaFile() { - return '\0'; -} - -/// @brief Opens a new file. -/// @param path -/// @param r -/// @return -_Output NodePtr HeFileSystemMgr::Open(_Input const Char* path, _Input const Char* r) { - if (!path || *path == 0) { - kout << "OpenHeFS: Open called with null or empty path\n"; - return nullptr; - } - if (!r || *r == 0) { - kout << "OpenHeFS: Open called with null or empty mode string\n"; - return nullptr; - } - return nullptr; -} - -Void HeFileSystemMgr::Write(_Input NodePtr node, _Input VoidPtr data, _Input Int32 flags, - _Input SizeT size) { - NE_UNUSED(node); - NE_UNUSED(flags); - NE_UNUSED(size); - NE_UNUSED(data); -} - -_Output VoidPtr HeFileSystemMgr::Read(_Input NodePtr node, _Input Int32 flags, _Input SizeT size) { - NE_UNUSED(node); - NE_UNUSED(flags); - NE_UNUSED(size); - - return nullptr; -} - -Void HeFileSystemMgr::Write(_Input const Char* name, _Input NodePtr node, _Input VoidPtr data, - _Input Int32 flags, _Input SizeT size) { - NE_UNUSED(node); - NE_UNUSED(flags); - NE_UNUSED(size); - NE_UNUSED(name); - NE_UNUSED(data); -} - -_Output VoidPtr HeFileSystemMgr::Read(_Input const Char* name, _Input NodePtr node, - _Input Int32 flags, _Input SizeT sz) { - NE_UNUSED(node); - NE_UNUSED(flags); - NE_UNUSED(sz); - NE_UNUSED(name); - - return nullptr; -} - -_Output Bool HeFileSystemMgr::Seek(NodePtr node, SizeT off) { - NE_UNUSED(node); - NE_UNUSED(off); - - return false; -} - -/// @brief Tell current offset within catalog. -/// @param node -/// @return kFileMgrNPos if invalid, else current offset. -_Output SizeT HeFileSystemMgr::Tell(NodePtr node) { - NE_UNUSED(node); - return kFileMgrNPos; -} - -/// @brief Rewinds the catalog -/// @param node -/// @return False if invalid, nah? calls Seek(node, 0). -_Output Bool HeFileSystemMgr::Rewind(NodePtr node) { - NE_UNUSED(node); - return kFileMgrNPos; -} - -/// @brief Returns the parser of OpenHeFS. -_Output HeFileSystemParser* HeFileSystemMgr::GetParser() noexcept { - return mParser; -} -} // namespace Kernel - -#endif // ifdef __FSKIT_INCLUDES_OPENHEFS__ -#endif // ifndef __NE_MINIMAL_OS__ diff --git a/dev/kernel/src/FS/OpenHeFS+FileSystemParser.cc b/dev/kernel/src/FS/OpenHeFS+FileSystemParser.cc deleted file mode 100644 index d8e22f18..00000000 --- a/dev/kernel/src/FS/OpenHeFS+FileSystemParser.cc +++ /dev/null @@ -1,1160 +0,0 @@ -/* ======================================== - - Copyright (C) 2024-2025 Amlal El Mahrouss, licensed under the Apache 2.0 license. - -======================================== */ - -#ifdef __FSKIT_INCLUDES_OPENHEFS__ - -#include <FSKit/OpenHeFS.h> -#include <FirmwareKit/EPM.h> -#include <FirmwareKit/GPT.h> -#include <KernelKit/KPC.h> -#include <KernelKit/ProcessScheduler.h> -#include <KernelKit/UserMgr.h> -#include <NeKit/Crc32.h> -#include <NeKit/KString.h> -#include <NeKit/KernelPanic.h> -#include <NeKit/Utils.h> -#include <modules/AHCI/AHCI.h> -#include <modules/ATA/ATA.h> - -namespace Kernel { -namespace Detail { - /// @brief Forward declarations of internal functions. - - /***********************************************************************************/ - /// @brief Traverse the RB-Tree of the filesystem. - /// @param dir The directory to traverse. - /// @param start The starting point of the traversal. - /// @note This function is used to traverse the RB-Tree of the filesystem. - /// @internal Internal filesystem use only. - /***********************************************************************************/ - STATIC ATTRIBUTE(unused) _Output Void - hefsi_traverse_tree(HEFS_INDEX_NODE_DIRECTORY* dir, DriveTrait* mnt, const Lba& start_ind, - Lba& start); - - /***********************************************************************************/ - /// @brief Get the index node of a file or directory. - /// @param boot The boot node of the filesystem. - /// @param mnt The mnt to read from. - /// @param dir_name The name of the directory. - /// @param file_name The name of the file. - /// @param kind The kind of the file (regular, directory, block, character, FIFO, socket, symbolic - /// link, unknown). - /***********************************************************************************/ - STATIC ATTRIBUTE(unused) _Output HEFS_INDEX_NODE* hefsi_fetch_in(HEFS_BOOT_NODE* boot, - DriveTrait* mnt, - const Utf8Char* dir_name, - const Utf8Char* file_name, - UInt8 kind); - - /***********************************************************************************/ - /// @brief Allocate a new index node-> - /// @param boot The boot node of the filesystem. - /// @param mnt The mnt to read/write from. - /// @param dir_name The name of the parent directory. - /// @return Status, see err_global_get(). - /***********************************************************************************/ - STATIC ATTRIBUTE(unused) _Output BOOL - hefsi_update_in_status(HEFS_BOOT_NODE* boot, DriveTrait* mnt, const Utf8Char* dir_name, - HEFS_INDEX_NODE* node, const BOOL create_or_delete); - - /***********************************************************************************/ - /// @brief Balance RB-Tree of the filesystem. - /// @param boot The boot node of the filesystem. - /// @param mnt The mnt to read/write from. - /// @return Status, see err_global_get(). - /***********************************************************************************/ - STATIC ATTRIBUTE(unused) _Output BOOL hefsi_balance_ind(HEFS_BOOT_NODE* boot, DriveTrait* mnt); - - /// @brief Alllocate IND from boot node. - /// @param boot The boot node of the filesystem. - /// @param mnt The mnt to read from. - /// @param dir_name The name of the directory. - /// @param dir_name The parent of the directory. - /// @param flags Directory flags. - /// @param delete_or_create Delete or create directory. - STATIC _Output BOOL hefsi_update_ind_status(HEFS_BOOT_NODE* boot, DriveTrait* mnt, - const Utf8Char* dir_name, UInt16 flags, - const BOOL delete_or_create); - - /// @brief This helper makes it easier for other machines to understand OpenHeFS encoded hashes. - STATIC UInt64 hefsi_to_big_endian_64(UInt64 val) { - return ((val >> 56) & 0x00000000000000FFULL) | ((val >> 40) & 0x000000000000FF00ULL) | - ((val >> 24) & 0x0000000000FF0000ULL) | ((val >> 8) & 0x00000000FF000000ULL) | - ((val << 8) & 0x000000FF00000000ULL) | ((val << 24) & 0x0000FF0000000000ULL) | - ((val << 40) & 0x00FF000000000000ULL) | ((val << 56) & 0xFF00000000000000ULL); - } - - /// @brief Simple algorithm to hash directory entries for INDs. - /// @param path the directory path. - /// @return The hashed path. - template <typename CharT = Utf8Char> - STATIC UInt64 hefsi_hash_64(const CharT* path) { - if (!path || *path == 0) return 0; - - const UInt64 kFnvBaseOffset = 0xcbf29ce484222325ULL; - const UInt64 kFnvPrimeNumber = 0x100000001b3ULL; - - UInt64 hash = kFnvBaseOffset; - - while (*path) { - hash ^= (CharT) (*path++); - hash *= kFnvPrimeNumber; - } - - return hefsi_to_big_endian_64(hash); - } - - /// @brief Traverse the RB-Tree of the filesystem. - /// @param dir The directory to traverse. - /// @param start The starting point of the traversal. - /// @note This function is used to traverse the RB-Tree of the filesystem. - /// @internal Internal filesystem use only. - STATIC ATTRIBUTE(unused) Void hefsi_traverse_tree(HEFS_INDEX_NODE_DIRECTORY* dir, DriveTrait* mnt, - const Lba& ind_start, Lba& start) { - if (!mnt || !dir) return; - - BOOL check_is_good = NO; - HEFS_INDEX_NODE_DIRECTORY* dir_tmp = new HEFS_INDEX_NODE_DIRECTORY(); - - while (YES) { - mnt->fPacket.fPacketLba = start; - mnt->fPacket.fPacketSize = sizeof(HEFS_INDEX_NODE_DIRECTORY); - mnt->fPacket.fPacketContent = dir_tmp; - mnt->fInput(mnt->fPacket); - - if (!mnt->fPacket.fPacketGood) break; - - if (dir_tmp->fNext != 0) { - if (check_is_good) break; - - start = dir_tmp->fNext; - - check_is_good = YES; - continue; - } else if (dir_tmp->fPrev != 0) { - if (check_is_good) break; - - start = dir_tmp->fPrev; - check_is_good = YES; - continue; - } else { - if (dir_tmp->fParent != 0) { - if (check_is_good) break; - - start = dir_tmp->fParent; - check_is_good = YES; - continue; - } else if (dir_tmp->fPrev != 0) { - if (check_is_good) break; - - start = dir_tmp->fPrev; - check_is_good = YES; - continue; - } else { - if (start == 0) { - start = ind_start; - continue; - } - - start += sizeof(HEFS_INDEX_NODE_DIRECTORY); - break; - } - } - } - - delete dir_tmp; - - start += sizeof(HEFS_INDEX_NODE_DIRECTORY); - if (start == 0) start = ind_start; - } - - /***********************************************************************************/ - /// @brief Rotate the RB-Tree to the left or right. - /// @internal - /***********************************************************************************/ - STATIC ATTRIBUTE(unused) _Output Void hefsi_rotate_tree(Lba& start, DriveTrait* mnt) { - if (!start || !mnt) return; - - HEFS_INDEX_NODE_DIRECTORY* cur = - (HEFS_INDEX_NODE_DIRECTORY*) RTL_ALLOCA(sizeof(HEFS_INDEX_NODE_DIRECTORY)); - - mnt->fPacket.fPacketLba = start; - mnt->fPacket.fPacketSize = sizeof(HEFS_INDEX_NODE_DIRECTORY); - mnt->fPacket.fPacketContent = cur; - - mnt->fInput(mnt->fPacket); - - if (cur->fHashPath == 0) return; - - HEFS_INDEX_NODE_DIRECTORY* sibling = - (HEFS_INDEX_NODE_DIRECTORY*) RTL_ALLOCA(sizeof(HEFS_INDEX_NODE_DIRECTORY)); - - mnt->fPacket.fPacketLba = cur->fPrev; - mnt->fPacket.fPacketSize = sizeof(HEFS_INDEX_NODE_DIRECTORY); - mnt->fPacket.fPacketContent = sibling; - - mnt->fInput(mnt->fPacket); - - if (sibling->fHashPath == 0) return; - - auto child_sibling = sibling->fChild; - auto child_cur = cur->fChild; - - cur->fChild = child_sibling; - sibling->fChild = child_cur; - - sibling->fChecksum = ke_calculate_crc32((Char*) sibling, sizeof(HEFS_INDEX_NODE_DIRECTORY)); - cur->fChecksum = ke_calculate_crc32((Char*) cur, sizeof(HEFS_INDEX_NODE_DIRECTORY)); - - mnt->fPacket.fPacketLba = cur->fParent; - mnt->fPacket.fPacketSize = sizeof(HEFS_INDEX_NODE_DIRECTORY); - mnt->fPacket.fPacketContent = sibling; - - mnt->fOutput(mnt->fPacket); - - mnt->fPacket.fPacketLba = start; - mnt->fPacket.fPacketSize = sizeof(HEFS_INDEX_NODE_DIRECTORY); - mnt->fPacket.fPacketContent = cur; - - mnt->fOutput(mnt->fPacket); - - HEFS_INDEX_NODE_DIRECTORY* sibling_child = - (HEFS_INDEX_NODE_DIRECTORY*) RTL_ALLOCA(sizeof(HEFS_INDEX_NODE_DIRECTORY)); - - mnt->fPacket.fPacketLba = child_sibling; - mnt->fPacket.fPacketSize = sizeof(HEFS_INDEX_NODE_DIRECTORY); - mnt->fPacket.fPacketContent = sibling_child; - - mnt->fInput(mnt->fPacket); - - sibling_child->fParent = cur->fParent; - - sibling_child->fChecksum = - ke_calculate_crc32((Char*) sibling, sizeof(HEFS_INDEX_NODE_DIRECTORY)); - - mnt->fOutput(mnt->fPacket); - - HEFS_INDEX_NODE_DIRECTORY* cur_child = - (HEFS_INDEX_NODE_DIRECTORY*) RTL_ALLOCA(sizeof(HEFS_INDEX_NODE_DIRECTORY)); - - mnt->fPacket.fPacketLba = child_cur; - mnt->fPacket.fPacketSize = sizeof(HEFS_INDEX_NODE_DIRECTORY); - mnt->fPacket.fPacketContent = cur_child; - - mnt->fInput(mnt->fPacket); - - cur_child->fParent = start; - - cur_child->fChecksum = ke_calculate_crc32((Char*) sibling, sizeof(HEFS_INDEX_NODE_DIRECTORY)); - - mnt->fOutput(mnt->fPacket); - - kout << "RB-Tree has been rotated.\r"; - } - - /// @brief Alllocate IND from boot node. - /// @param boot The boot node of the filesystem. - /// @param mnt The mnt to read from. - /// @param dir_name The name of the directory. - /// @param dir_name The parent of the directory. - /// @param flags Directory flags. - /// @param delete_or_create Delete or create directory. - STATIC _Output BOOL hefsi_update_ind_status(HEFS_BOOT_NODE* boot, DriveTrait* mnt, - const Utf8Char* dir_name, UInt16 flags, - const BOOL delete_or_create) { - if (mnt) { - HEFS_INDEX_NODE_DIRECTORY* tmpdir = - (HEFS_INDEX_NODE_DIRECTORY*) mm_alloc_ptr(sizeof(HEFS_INDEX_NODE_DIRECTORY), Yes, No); - - auto start = boot->fStartIND; - auto prev_location = start; - auto parent_location = 0UL; - - MUST_PASS(boot->fStartIND > mnt->fLbaStart); - - while (YES) { - auto prev_start = start; - - if (start) - mnt->fPacket.fPacketLba = start; - else - mnt->fPacket.fPacketLba = prev_location + sizeof(HEFS_INDEX_NODE_DIRECTORY); - - mnt->fPacket.fPacketSize = sizeof(HEFS_INDEX_NODE_DIRECTORY); - mnt->fPacket.fPacketContent = tmpdir; - - mnt->fInput(mnt->fPacket); - - BOOL expr = NO; - - if (!delete_or_create) { - expr = (!tmpdir->fCreated && tmpdir->fDeleted) || tmpdir->fHashPath == 0; - } else { - expr = - tmpdir->fCreated && !tmpdir->fDeleted && hefsi_hash_64(dir_name) == tmpdir->fHashPath; - } - - if (expr) { - HEFS_INDEX_NODE_DIRECTORY* dirent = - (HEFS_INDEX_NODE_DIRECTORY*) mm_alloc_ptr(sizeof(HEFS_INDEX_NODE_DIRECTORY), Yes, No); - - rt_set_memory(dirent, 0, sizeof(HEFS_INDEX_NODE_DIRECTORY)); - - dirent->fHashPath = delete_or_create ? 0UL : hefsi_hash_64(dir_name); - dirent->fAccessed = 0UL; - dirent->fCreated = delete_or_create ? 0UL : 1UL; - dirent->fDeleted = delete_or_create ? 1UL : 0UL; - dirent->fModified = 0UL; - dirent->fEntryCount = 0UL; - - dirent->fReserved = 0; - dirent->fFlags = flags; - dirent->fChecksum = 0; - - dirent->fEntryCount = 0; - - if (parent_location) { - HEFS_INDEX_NODE_DIRECTORY* tmpend = - (HEFS_INDEX_NODE_DIRECTORY*) RTL_ALLOCA(sizeof(HEFS_INDEX_NODE_DIRECTORY)); - - mnt->fPacket.fPacketLba = parent_location; - mnt->fPacket.fPacketSize = sizeof(HEFS_INDEX_NODE_DIRECTORY); - mnt->fPacket.fPacketContent = tmpend; - - mnt->fInput(mnt->fPacket); - - if (tmpend->fChecksum != - ke_calculate_crc32((Char*) tmpend, sizeof(HEFS_INDEX_NODE_DIRECTORY))) - ke_panic(RUNTIME_CHECK_FILESYSTEM, "Bad CRC32 value, aborting."); - - if (delete_or_create) - --tmpend->fEntryCount; - else - ++tmpend->fEntryCount; - - tmpend->fChecksum = - ke_calculate_crc32((Char*) tmpend, sizeof(HEFS_INDEX_NODE_DIRECTORY)); - - mnt->fOutput(mnt->fPacket); - - auto child_first = tmpend->fChild; - - while (YES) { - mnt->fPacket.fPacketLba = child_first; - mnt->fPacket.fPacketSize = sizeof(HEFS_INDEX_NODE_DIRECTORY); - mnt->fPacket.fPacketContent = tmpend; - - mnt->fInput(mnt->fPacket); - - if ((!tmpend->fCreated && tmpend->fDeleted) || tmpend->fHashPath == 0) { - start = child_first; - break; - } - - hefsi_traverse_tree(tmpend, mnt, boot->fStartIND, child_first); - } - } - - dirent->fNext = tmpdir->fNext; - dirent->fPrev = tmpdir->fPrev; - dirent->fParent = tmpdir->fParent; - dirent->fChild = tmpdir->fChild; - dirent->fColor = tmpdir->fColor; - - if (dirent->fColor == 0) { - dirent->fColor = dirent->fNext ? kHeFSRed : kHeFSBlack; - } - - if (dirent->fPrev == 0) { - dirent->fPrev = boot->fStartIND; - } - - if (dirent->fParent == 0) { - dirent->fParent = boot->fStartIND; - } - - if (tmpdir->fChild == 0) { - auto child = dirent->fNext + sizeof(HEFS_INDEX_NODE_DIRECTORY); - - HEFS_INDEX_NODE_DIRECTORY* tmpend = - (HEFS_INDEX_NODE_DIRECTORY*) RTL_ALLOCA(sizeof(HEFS_INDEX_NODE_DIRECTORY)); - - while (YES) { - mnt->fPacket.fPacketLba = child; - mnt->fPacket.fPacketSize = sizeof(HEFS_INDEX_NODE_DIRECTORY); - mnt->fPacket.fPacketContent = tmpend; - - mnt->fInput(mnt->fPacket); - - if ((!tmpend->fCreated && tmpend->fDeleted) || tmpdir->fHashPath == 0) { - break; - } - - child += sizeof(HEFS_INDEX_NODE_DIRECTORY); - if (child > boot->fEndIND) break; - } - - dirent->fColor = kHeFSRed; - dirent->fChild = child; - - if (child > boot->fEndIND) dirent->fChild = boot->fStartIND; - } - - for (SizeT index = 0UL; index < kHeFSSliceCount; ++index) { - dirent->fINSlices[index] = 0UL; - } - - dirent->fChecksum = ke_calculate_crc32((Char*) dirent, sizeof(HEFS_INDEX_NODE_DIRECTORY)); - - mnt->fPacket.fPacketLba = prev_start; - mnt->fPacket.fPacketSize = sizeof(HEFS_INDEX_NODE_DIRECTORY); - mnt->fPacket.fPacketContent = dirent; - - mnt->fOutput(mnt->fPacket); - - err_global_get() = kErrorSuccess; - - mm_free_ptr(dirent); - mm_free_ptr(tmpdir); - - if (!delete_or_create) - ++boot->fINDCount; - else - --boot->fINDCount; - - boot->fChecksum = ke_calculate_crc32((Char*) boot, sizeof(HEFS_BOOT_NODE)); - - mnt->fPacket.fPacketLba = mnt->fLbaStart; - mnt->fPacket.fPacketSize = sizeof(HEFS_BOOT_NODE); - mnt->fPacket.fPacketContent = boot; - - mnt->fOutput(mnt->fPacket); - - return YES; - } - - prev_location = start; - - hefsi_traverse_tree(tmpdir, mnt, boot->fStartIND, start); - if (start > boot->fEndIND || start == 0) break; - } - - err_global_get() = kErrorDisk; - mm_free_ptr(tmpdir); - - return NO; - } - - err_global_get() = kErrorDiskIsFull; - return NO; - } - - /// @brief Get the index node of a file or directory. - /// @param boot The boot node of the filesystem. - /// @param mnt The mnt to read from. - /// @param dir_name The name of the directory. - /// @param file_name The name of the file. - /// @param kind The kind of the file (regular, directory, block, character, FIFO, socket, symbolic - /// link, unknown). - STATIC ATTRIBUTE(unused) _Output HEFS_INDEX_NODE* hefsi_fetch_in(HEFS_BOOT_NODE* boot, - DriveTrait* mnt, - const Utf8Char* dir_name, - const Utf8Char* file_name, - UInt8 kind) { - if (mnt) { - if (boot->fStartIND > boot->fEndIND) return nullptr; - if (boot->fStartIN > boot->fEndIN) return nullptr; - - auto start = boot->fStartIND; - HEFS_INDEX_NODE* node = new HEFS_INDEX_NODE(); - - HEFS_INDEX_NODE_DIRECTORY* dir = - (HEFS_INDEX_NODE_DIRECTORY*) mm_alloc_ptr(sizeof(HEFS_INDEX_NODE_DIRECTORY), Yes, No); - - while (YES) { - if (err_global_get() == kErrorDiskIsCorrupted) { - delete dir; - dir = nullptr; - - delete node; - node = nullptr; - - return nullptr; - } - - mnt->fPacket.fPacketLba = start; - mnt->fPacket.fPacketSize = sizeof(HEFS_INDEX_NODE_DIRECTORY); - mnt->fPacket.fPacketContent = dir; - - mnt->fInput(mnt->fPacket); - - (Void)(kout << hex_number(hefsi_hash_64(dir_name)) << kendl); - (Void)(kout << hex_number(dir->fHashPath) << kendl); - - if (dir->fHashPath == 0) break; - - if (hefsi_hash_64(dir_name) == dir->fHashPath) { - for (SizeT inode_index = 0UL; inode_index < kHeFSSliceCount; ++inode_index) { - mnt->fPacket.fPacketLba = dir->fINSlices[inode_index]; - mnt->fPacket.fPacketSize = sizeof(HEFS_INDEX_NODE); - mnt->fPacket.fPacketContent = node; - - mnt->fInput(mnt->fPacket); - - (Void)(kout << hex_number(hefsi_hash_64(file_name)) << kendl); - (Void)(kout << hex_number(node->fHashPath) << kendl); - - if (hefsi_hash_64(file_name) == node->fHashPath && node->fKind == kind) { - delete dir; - dir = nullptr; - - return node; - } - } - } - - hefsi_traverse_tree(dir, mnt, boot->fStartIND, start); - if (start == boot->fStartIND || start == boot->fStartIND) break; - } - - delete node; - node = nullptr; - - delete dir; - dir = nullptr; - } - - kout << "Error: Failed to find IN.\r"; - - err_global_get() = kErrorFileNotFound; - - return nullptr; - } - - STATIC ATTRIBUTE(unused) _Output BOOL - hefsi_update_in_status(HEFS_BOOT_NODE* boot, DriveTrait* mnt, const Utf8Char* dir_name, - HEFS_INDEX_NODE* node, BOOL delete_or_create) { - if (!boot || !mnt) return NO; - - auto start = boot->fStartIND; - - if (start > boot->fEndIND) return NO; - if (boot->fStartIN > boot->fEndIN) return NO; - ; - if (boot->fStartBlock > boot->fEndBlock) return NO; - - if (mnt) { - HEFS_INDEX_NODE_DIRECTORY* dir = - (HEFS_INDEX_NODE_DIRECTORY*) mm_alloc_ptr(sizeof(HEFS_INDEX_NODE_DIRECTORY), Yes, No); - - auto hash_file = node->fHashPath; - - while (YES) { - mnt->fPacket.fPacketLba = start; - mnt->fPacket.fPacketSize = sizeof(HEFS_INDEX_NODE_DIRECTORY); - mnt->fPacket.fPacketContent = dir; - - mnt->fInput(mnt->fPacket); - - (Void)(kout << hex_number(hefsi_hash_64(dir_name)) << kendl); - (Void)(kout << hex_number(dir->fHashPath) << kendl); - - if (hefsi_hash_64(dir_name) == dir->fHashPath) { - for (SizeT inode_index = 0UL; inode_index < kHeFSSliceCount; ++inode_index) { - if (dir->fINSlices[inode_index] == 0 && !delete_or_create) { - dir->fINSlices[inode_index] = boot->fStartIN; - - ++dir->fEntryCount; - - dir->fChecksum = ke_calculate_crc32((Char*) dir, sizeof(HEFS_INDEX_NODE_DIRECTORY)); - - mnt->fPacket.fPacketLba = start; - mnt->fPacket.fPacketSize = sizeof(HEFS_INDEX_NODE_DIRECTORY); - mnt->fPacket.fPacketContent = dir; - - mnt->fOutput(mnt->fPacket); - - auto lba = dir->fINSlices[inode_index]; - - node->fOffsetSliceLow = (UInt32) (boot->fStartBlock); - node->fOffsetSliceHigh = (UInt32) (boot->fStartBlock >> 32); - - node->fChecksum = ke_calculate_crc32((Char*) node, sizeof(HEFS_INDEX_NODE)); - - mnt->fPacket.fPacketLba = lba; - mnt->fPacket.fPacketSize = sizeof(HEFS_INDEX_NODE); - mnt->fPacket.fPacketContent = node; - - mnt->fOutput(mnt->fPacket); - - boot->fStartIN += sizeof(HEFS_INDEX_NODE); - boot->fStartBlock += kHeFSBlockLen; - - boot->fChecksum = ke_calculate_crc32((Char*) boot, sizeof(HEFS_BOOT_NODE)); - - mnt->fPacket.fPacketLba = mnt->fLbaStart; - mnt->fPacket.fPacketSize = sizeof(HEFS_BOOT_NODE); - mnt->fPacket.fPacketContent = boot; - - mnt->fOutput(mnt->fPacket); - - mm_free_ptr(dir); - - return YES; - } else if (dir->fINSlices[inode_index] != 0 && delete_or_create) { - auto lba = dir->fINSlices[inode_index]; - - HEFS_INDEX_NODE tmp_node{}; - - mnt->fPacket.fPacketLba = lba; - mnt->fPacket.fPacketSize = sizeof(HEFS_INDEX_NODE); - mnt->fPacket.fPacketContent = &tmp_node; - - mnt->fInput(mnt->fPacket); - - if (tmp_node.fHashPath != hash_file) { - continue; - } - - node->fOffsetSliceLow = 0; - node->fOffsetSliceHigh = 0; - - boot->fStartIN -= sizeof(HEFS_INDEX_NODE); - boot->fStartBlock -= kHeFSBlockLen; - - boot->fChecksum = ke_calculate_crc32((Char*) boot, sizeof(HEFS_BOOT_NODE)); - - mnt->fPacket.fPacketLba = mnt->fLbaStart; - mnt->fPacket.fPacketSize = sizeof(HEFS_BOOT_NODE); - mnt->fPacket.fPacketContent = boot; - - mnt->fOutput(mnt->fPacket); - - mnt->fPacket.fPacketLba = lba; - mnt->fPacket.fPacketSize = sizeof(HEFS_INDEX_NODE); - mnt->fPacket.fPacketContent = node; - - mnt->fOutput(mnt->fPacket); - - dir->fINSlices[inode_index] = 0; - - if (dir->fEntryCount) --dir->fEntryCount; - - dir->fChecksum = ke_calculate_crc32((Char*) dir, sizeof(HEFS_INDEX_NODE_DIRECTORY)); - - mnt->fPacket.fPacketLba = start; - mnt->fPacket.fPacketSize = sizeof(HEFS_INDEX_NODE_DIRECTORY); - mnt->fPacket.fPacketContent = dir; - - mnt->fOutput(mnt->fPacket); - - mm_free_ptr(dir); - - return YES; - } - } - } - - hefsi_traverse_tree(dir, mnt, boot->fStartIND, start); - if (start > boot->fEndIND || start == 0) break; - } - - mm_free_ptr(dir); - err_global_get() = kErrorFileNotFound; - return NO; - } - - err_global_get() = kErrorDiskIsFull; - return NO; - } - - /// @brief Balance RB-Tree of the filesystem. - /// @param boot The boot node of the filesystem. - /// @param mnt The mnt to read/write from. - /// @return Status, see err_global_get(). - STATIC ATTRIBUTE(unused) _Output BOOL hefsi_balance_ind(HEFS_BOOT_NODE* boot, DriveTrait* mnt) { - if (mnt) { - HEFS_INDEX_NODE_DIRECTORY* dir = - (HEFS_INDEX_NODE_DIRECTORY*) RTL_ALLOCA(sizeof(HEFS_INDEX_NODE_DIRECTORY)); - - auto start = boot->fStartIND; - - while (YES) { - if (start == 0UL || start > boot->fEndIND) break; - - mnt->fPacket.fPacketLba = start; - mnt->fPacket.fPacketSize = sizeof(HEFS_INDEX_NODE_DIRECTORY); - mnt->fPacket.fPacketContent = dir; - - mnt->fInput(mnt->fPacket); - - if (!mnt->fPacket.fPacketGood) { - err_global_get() = kErrorDiskIsCorrupted; - - return NO; - } - - if (start == boot->fStartIND) { - dir->fColor = kHeFSBlack; - - mnt->fPacket.fPacketLba = start; - mnt->fPacket.fPacketSize = sizeof(HEFS_INDEX_NODE_DIRECTORY); - mnt->fPacket.fPacketContent = dir; - - mnt->fOutput(mnt->fPacket); - } - - if (dir->fColor == kHeFSBlack && dir->fChild != 0UL) { - dir->fColor = kHeFSRed; - hefsi_rotate_tree(start, mnt); - } else if (dir->fColor == kHeFSBlack && dir->fChild == 0UL) { - dir->fColor = kHeFSBlack; - - mnt->fPacket.fPacketLba = start; - mnt->fPacket.fPacketSize = sizeof(HEFS_INDEX_NODE_DIRECTORY); - mnt->fPacket.fPacketContent = dir; - - mnt->fOutput(mnt->fPacket); - } - - if (ke_calculate_crc32((Char*) dir, sizeof(HEFS_INDEX_NODE_DIRECTORY)) != dir->fChecksum) { - dir->fChecksum = ke_calculate_crc32((Char*) dir, sizeof(HEFS_INDEX_NODE_DIRECTORY)); - - mnt->fPacket.fPacketLba = start; - mnt->fPacket.fPacketSize = sizeof(HEFS_INDEX_NODE_DIRECTORY); - mnt->fPacket.fPacketContent = dir; - - mnt->fOutput(mnt->fPacket); - } - - hefsi_traverse_tree(dir, mnt, boot->fStartIND, start); - } - - err_global_get() = kErrorSuccess; - return YES; - } - - err_global_get() = kErrorDisk; - return NO; - } -} // namespace Detail -} // namespace Kernel - -/// @note OpenHeFS will allocate inodes and ind in advance, to avoid having to allocate them in -/// real-time. -/// @note This is certainly take longer to format a disk with it, but worth-it in the long run. - -namespace Kernel { -/// @brief Make a EPM+OpenHeFS mnt out of the disk. -/// @param mnt The mnt to write on. -/// @return If it was sucessful, see err_local_get(). -_Output Bool HeFileSystemParser::Format(_Input _Output DriveTrait* mnt, _Input const Int32 flags, - _Input const Utf8Char* vol_name) { - // Verify Disk. - mnt->fVerify(mnt->fPacket); - - // if disk isn't good, then error out. - if (false == mnt->fPacket.fPacketGood) { - err_global_get() = kErrorDiskIsCorrupted; - return NO; - } - - if (drv_std_get_size() < kHeFSMinimumDiskSize) { - (Void)(kout << "OpenHeFS recommends at least 128 GiB of free space." << kendl); - } - - HEFS_BOOT_NODE* boot = (HEFS_BOOT_NODE*) RTL_ALLOCA(sizeof(HEFS_BOOT_NODE)); - - mnt->fPacket.fPacketLba = mnt->fLbaStart; - mnt->fPacket.fPacketSize = sizeof(HEFS_BOOT_NODE); - mnt->fPacket.fPacketContent = boot; - - mnt->fInput(mnt->fPacket); - - if (!mnt->fPacket.fPacketGood) { - err_global_get() = kErrorDiskIsCorrupted; - - return NO; - } - - // Check if the disk is already formatted. - - if (KStringBuilder::Equals(boot->fMagic, kHeFSMagic) && boot->fVersion == kHeFSVersion) { - if (ke_calculate_crc32((Char*) boot, sizeof(HEFS_BOOT_NODE)) != boot->fChecksum && - boot->fChecksum > 0) { - err_global_get() = kErrorDiskIsCorrupted; - return NO; - } - - err_global_get() = kErrorSuccess; - return YES; - } - - if (ke_calculate_crc32((Char*) boot, sizeof(HEFS_BOOT_NODE)) != boot->fChecksum && - boot->fChecksum > 0) { - err_global_get() = kErrorDiskIsCorrupted; - return NO; - } - - rt_copy_memory_safe((VoidPtr) "fs/hefs-packet", mnt->fPacket.fPacketMime, - rt_string_len("fs/hefs-packet"), sizeof(mnt->fPacket.fPacketMime)); - - urt_copy_memory((VoidPtr) vol_name, boot->fVolName, urt_string_len(vol_name) + 1); - rt_copy_memory_safe((VoidPtr) kHeFSMagic, boot->fMagic, kHeFSMagicLen - 1, sizeof(boot->fMagic)); - - if (mnt->fLbaStart > mnt->fLbaEnd) { - err_global_get() = kErrorDiskIsCorrupted; - - return NO; - } - - boot->fBadSectors = 0; - - boot->fSectorCount = drv_std_get_sector_count(); - boot->fSectorSize = mnt->fSectorSz; - - MUST_PASS(boot->fSectorSize); - - /// @note all OpenHeFS strucutres are equal to 512, so here it's fine, unless fSectoSize is 2048. - const SizeT max_lba = (drv_std_get_size()) / boot->fSectorSize; - - const SizeT dir_max = max_lba / 300; // 5% for directory inodes - const SizeT inode_max = max_lba / 400; // 5% for inodes - - boot->fStartIND = mnt->fLbaStart + kHeFSINDStartOffset; - boot->fEndIND = boot->fStartIND + dir_max; - - boot->fStartIN = boot->fEndIND; - boot->fEndIN = boot->fStartIN + inode_max; - - boot->fStartBlock = boot->fEndIN; - boot->fEndBlock = drv_std_get_size(); - - boot->fINDCount = 0; - - boot->fDiskSize = drv_std_get_size(); - boot->fDiskStatus = kHeFSStatusUnlocked; - - boot->fDiskFlags = flags; - - if (mnt->fKind & kMassStorageDrive) { - boot->fDiskKind = kHeFSMassStorageDevice; - } else if (mnt->fKind & kHeFSOpticalDrive) { - boot->fDiskKind = kHeFSOpticalDrive; - } else { - boot->fDiskKind = kHeFSUnknown; - } - - boot->fVersion = kHeFSVersion; - - boot->fVID = kHeFSInvalidVID; - - boot->fChecksum = ke_calculate_crc32((Char*) boot, sizeof(HEFS_BOOT_NODE)); - - mnt->fPacket.fPacketLba = mnt->fLbaStart; - mnt->fPacket.fPacketSize = sizeof(HEFS_BOOT_NODE); - mnt->fPacket.fPacketContent = boot; - - mnt->fOutput(mnt->fPacket); - - (Void)(kout << "Protocol: " << mnt->fProtocol() << kendl); - (Void)(kout8 << u8"Volume Name: " << boot->fVolName << kendl8); - (Void)(kout << "Start IND: " << hex_number(boot->fStartIND) << kendl); - (Void)(kout << "End IND: " << hex_number(boot->fEndIND) << kendl); - (Void)(kout << "Start IN: " << hex_number(boot->fStartIN) << kendl); - (Void)(kout << "End IN: " << hex_number(boot->fEndIN) << kendl); - (Void)(kout << "Start Block: " << hex_number(boot->fStartBlock) << kendl); - (Void)(kout << "End Block: " << hex_number(boot->fEndBlock) << kendl); - (Void)(kout << "Number of IND: " << hex_number(boot->fINDCount) << kendl); - (Void)(kout << "Sector Size: " << hex_number(boot->fSectorSize) << kendl); - (Void)(kout << "Drive Kind: " << Detail::hefs_drive_kind_to_string(boot->fDiskKind) << kendl); - - if (!mnt->fPacket.fPacketGood) { - err_global_get() = kErrorDiskIsCorrupted; - return NO; - } - - /// AMLALE: Better way to create default directories than before. - const Utf8Char* kFileMap[] = {u8"/", u8"/boot", u8"/system", u8"/network", - u8"/devices", u8"/media", u8"/dev", (Utf8Char*) nullptr}; - - SizeT i = 0; - while (kFileMap[++i] != nullptr) { - this->CreateINodeDirectory(mnt, kHeFSEncodingFlagsUTF8, kFileMap[i]); - } - - err_global_get() = kErrorSuccess; - - return YES; -} - -/// @brief Create a new directory on the disk. -/// @param mnt The mnt to write on. -/// @param flags The flags to use. -/// @param dir The directory to create the file in. -/// @return If it was sucessful, see err_local_get(). -_Output Bool HeFileSystemParser::INodeDirectoryCtlManip(_Input DriveTrait* mnt, - _Input const Int32 flags, - const Utf8Char* dir, - const BOOL delete_or_create) { - if (urt_string_len(dir) > kHeFSFileNameLen) { - err_global_get() = kErrorDisk; - return NO; - } - - HEFS_BOOT_NODE* boot = (HEFS_BOOT_NODE*) mm_alloc_ptr(sizeof(HEFS_BOOT_NODE), Yes, No); - - rt_copy_memory_safe((VoidPtr) "fs/hefs-packet", mnt->fPacket.fPacketMime, - rt_string_len("fs/hefs-packet"), sizeof(mnt->fPacket.fPacketMime)); - - mnt->fPacket.fPacketLba = mnt->fLbaStart; - mnt->fPacket.fPacketSize = sizeof(HEFS_BOOT_NODE); - mnt->fPacket.fPacketContent = boot; - - mnt->fInput(mnt->fPacket); - - if (!KStringBuilder::Equals(boot->fMagic, kHeFSMagic) || boot->fVersion != kHeFSVersion) { - err_global_get() = kErrorDisk; - return YES; - } - - if (!KStringBuilder::Equals(boot->fMagic, kHeFSMagic) || boot->fVersion != kHeFSVersion) { - err_global_get() = kErrorDiskIsCorrupted; - - kout << "Invalid Boot Node, this can't continue!\r"; - - return NO; - } - - if (KStringBuilder::Equals(dir, kHeFSSearchAllStr)) { - kout << "Error: Invalid directory name.\r"; - - err_global_get() = kErrorInvalidData; - - return NO; - } - - if (Detail::hefsi_update_ind_status(boot, mnt, dir, flags, delete_or_create)) { - // todo: make it smarter for high-throughput. - Detail::hefsi_balance_ind(boot, mnt); - - mm_free_ptr((VoidPtr) boot); - return YES; - } - - mm_free_ptr((VoidPtr) boot); - return NO; -} - -_Output Bool HeFileSystemParser::RemoveINodeDirectory(_Input DriveTrait* mnt, - _Input const Int32 flags, - const Utf8Char* dir) { - return this->INodeDirectoryCtlManip(mnt, flags, dir, YES); -} - -_Output Bool HeFileSystemParser::CreateINodeDirectory(_Input DriveTrait* mnt, - _Input const Int32 flags, - const Utf8Char* dir) { - return this->INodeDirectoryCtlManip(mnt, flags, dir, NO); -} - -_Output Bool HeFileSystemParser::DeleteINode(_Input DriveTrait* mnt, _Input const Int32 flags, - const Utf8Char* dir, const Utf8Char* name, - const UInt8 kind) { - return this->INodeCtlManip(mnt, flags, dir, name, YES, kind); -} - -_Output Bool HeFileSystemParser::CreateINode(_Input DriveTrait* mnt, _Input const Int32 flags, - const Utf8Char* dir, const Utf8Char* name, - const UInt8 kind) { - return this->INodeCtlManip(mnt, flags, dir, name, NO, kind); -} - -_Output Bool HeFileSystemParser::INodeManip(_Input DriveTrait* mnt, VoidPtr block, SizeT block_sz, - const Utf8Char* dir, const Utf8Char* name, - const UInt8 kind, const BOOL is_input) { - if (urt_string_len(dir) > kHeFSFileNameLen) { - err_global_get() = kErrorDisk; - return NO; - } - - if (urt_string_len(name) > kHeFSFileNameLen) { - err_global_get() = kErrorDisk; - return NO; - } - - HEFS_BOOT_NODE* boot = (HEFS_BOOT_NODE*) mm_alloc_ptr(sizeof(HEFS_BOOT_NODE), Yes, No); - - if (!boot) { - err_global_get() = kErrorInvalidData; - return NO; - } - - rt_copy_memory_safe((VoidPtr) "fs/hefs-packet", mnt->fPacket.fPacketMime, - rt_string_len("fs/hefs-packet"), sizeof(mnt->fPacket.fPacketMime)); - - mnt->fPacket.fPacketLba = mnt->fLbaStart; - mnt->fPacket.fPacketSize = sizeof(HEFS_BOOT_NODE); - mnt->fPacket.fPacketContent = boot; - - mnt->fInput(mnt->fPacket); - - if (!KStringBuilder::Equals(boot->fMagic, kHeFSMagic) || boot->fVersion != kHeFSVersion) { - (Void)(kout << "Invalid Boot Node, OpenHeFS partition is invalid." << kendl); - mm_free_ptr((VoidPtr) boot); - err_global_get() = kErrorDisk; - return NO; - } - - auto start = Detail::hefsi_fetch_in(boot, mnt, dir, name, kind); - - if (start) { - (Void)(kout << hex_number(start->fHashPath) << kendl); - (Void)(kout << hex_number(start->fOffsetSliceLow) << kendl); - - if (start->fOffsetSliceLow && start->fHashPath) { - mnt->fPacket.fPacketLba = ((UInt64) start->fOffsetSliceHigh << 32) | start->fOffsetSliceLow; - mnt->fPacket.fPacketSize = block_sz; - mnt->fPacket.fPacketContent = block; - - if (is_input) { - mnt->fInput(mnt->fPacket); - } else { - if (start->fFlags & kHeFSFlagsReadOnly) { - mm_free_ptr((VoidPtr) boot); - delete start; - - kout << "Error: File is read-only\r"; - - return NO; - } - - mnt->fOutput(mnt->fPacket); - } - } - } - - mm_free_ptr((VoidPtr) boot); - delete start; - return YES; -} - -/// @brief Create a new file on the disk. -/// @param mnt The mnt to write on. -/// @param flags The flags to use. -/// @param dir The directory to create the file in. -/// @param name The name of the file. -/// @return If it was sucessful, see err_local_get(). -_Output Bool HeFileSystemParser::INodeCtlManip(_Input DriveTrait* mnt, _Input const Int32 flags, - const Utf8Char* dir, const Utf8Char* name, - const BOOL delete_or_create, const UInt8 kind) { - if (urt_string_len(name) > kHeFSFileNameLen) { - err_global_get() = kErrorDisk; - return NO; - } - - if (urt_string_len(dir) > kHeFSFileNameLen) { - err_global_get() = kErrorDisk; - return NO; - } - - HEFS_INDEX_NODE* node = (HEFS_INDEX_NODE*) mm_alloc_ptr(sizeof(HEFS_INDEX_NODE), Yes, No); - - if (!node) { - err_global_get() = kErrorInvalidData; - return NO; - } - - rt_set_memory(node, 0, sizeof(HEFS_INDEX_NODE)); - - HEFS_BOOT_NODE* boot = (HEFS_BOOT_NODE*) RTL_ALLOCA(sizeof(HEFS_BOOT_NODE)); - - if (!boot) { - mm_free_ptr((VoidPtr) node); - err_global_get() = kErrorInvalidData; - - return NO; - } - - rt_copy_memory_safe((VoidPtr) "fs/hefs-packet", mnt->fPacket.fPacketMime, - rt_string_len("fs/hefs-packet"), sizeof(mnt->fPacket.fPacketMime)); - - mnt->fPacket.fPacketLba = mnt->fLbaStart; - mnt->fPacket.fPacketSize = sizeof(HEFS_BOOT_NODE); - mnt->fPacket.fPacketContent = boot; - - mnt->fInput(mnt->fPacket); - - if (!KStringBuilder::Equals(boot->fMagic, kHeFSMagic) || boot->fVersion != kHeFSVersion) { - err_global_get() = kErrorDisk; - return YES; - } - - if (KStringBuilder::Equals(dir, kHeFSSearchAllStr)) { - kout << "Error: Invalid file name.\r"; - - err_global_get() = kErrorInvalidData; - return NO; - } - - for (SizeT i_name = 0UL; i_name < urt_string_len(name); ++i_name) { - if (name[i_name] == u'/') { - err_global_get() = kErrorInvalidData; - return NO; - } - } - - if (KStringBuilder::Equals(dir, kHeFSSearchAllStr)) { - kout << "Error: Invalid directory name.\r"; - - err_global_get() = kErrorInvalidData; - return NO; - } - - node->fAccessed = 0; - node->fCreated = delete_or_create ? NO : YES; - node->fDeleted = delete_or_create ? 1UL : NO; - node->fModified = 0; - node->fSize = 0; - node->fKind = kind; - node->fFlags = flags; - node->fChecksum = 0; - node->fGID = 0; - node->fUID = 0; - node->fHashPath = Detail::hefsi_hash_64(name); - - if (Detail::hefsi_update_in_status(boot, mnt, dir, node, delete_or_create)) { - mm_free_ptr((VoidPtr) node); - - Detail::hefsi_balance_ind(boot, mnt); - - err_global_get() = kErrorSuccess; - return YES; - } - - mm_free_ptr((VoidPtr) node); - err_global_get() = kErrorDirectoryNotFound; - - return NO; -} - -STATIC IMountpoint kMountpoint; - -/// @brief Initialize the OpenHeFS filesystem. -/// @return To check its status, see err_local_get(). -Boolean OpenHeFS::fs_init_openhefs(Void) noexcept { - io_construct_main_drive(kMountpoint.A()); - - if (kMountpoint.A().fPacket.fPacketReadOnly == YES) { - kout << "Main disk cannot be mounted (read-only media).\r"; - return YES; - } - - return HeFileSystemParser{}.Format(&kMountpoint.A(), kHeFSEncodingFlagsUTF8, kHeFSDefaultVolumeName); -} -} // namespace Kernel - -#endif // ifdef __FSKIT_INCLUDES_OPENHEFS__ |
