summaryrefslogtreecommitdiffhomepage
path: root/dev/kernel/src/FS
diff options
context:
space:
mode:
authorAmlal El Mahrouss <amlal@nekernel.org>2025-11-24 03:02:43 +0100
committerAmlal El Mahrouss <amlal@nekernel.org>2025-11-24 03:02:43 +0100
commit83d870e58457a1d335a1d9b9966a6a1887cc297b (patch)
tree72888f88c7728c82f3f6df1f4f70591de15eab36 /dev/kernel/src/FS
parentab37adbacf0f33845804c788b39680cd754752a8 (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.cc1555
-rw-r--r--dev/kernel/src/FS/NeFS+FileMgr.cc276
-rw-r--r--dev/kernel/src/FS/NeFS+FileSystemParser.cc870
-rw-r--r--dev/kernel/src/FS/OpenHeFS+FileMgr.cc191
-rw-r--r--dev/kernel/src/FS/OpenHeFS+FileSystemParser.cc1160
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__