summaryrefslogtreecommitdiffhomepage
path: root/Private/Source/FS
diff options
context:
space:
mode:
authorAmlal El Mahrouss <amlal.elmahrouss@icloud.com>2024-04-21 08:53:36 +0200
committerAmlal El Mahrouss <amlal.elmahrouss@icloud.com>2024-04-21 08:53:36 +0200
commitebadabf4b6ab4a08c47b098affa0de6d681b5982 (patch)
tree477087431fd2bbee9217390ab370dff30f0a2bf0 /Private/Source/FS
parentbc4f32c10a34c6bded98f378004f7435deede43b (diff)
MHR-8: IMP: Implement an allocator for catalog and forks.
- Implement ke_find_free_catalog and ke_find_free_fork. Signed-off-by: Amlal El Mahrouss <amlal.elmahrouss@icloud.com>
Diffstat (limited to 'Private/Source/FS')
-rw-r--r--Private/Source/FS/NewFS.cxx148
1 files changed, 130 insertions, 18 deletions
diff --git a/Private/Source/FS/NewFS.cxx b/Private/Source/FS/NewFS.cxx
index 216db7c6..7eb79d10 100644
--- a/Private/Source/FS/NewFS.cxx
+++ b/Private/Source/FS/NewFS.cxx
@@ -7,13 +7,16 @@
#ifdef __FSKIT_NEWFS__
#include <FSKit/NewFS.hxx>
+#include <KernelKit/HError.hpp>
+#include <NewKit/Crc32.hpp>
#include <NewKit/Utils.hpp>
using namespace NewOS;
-STATIC Lba ke_find_free_fork(SizeT sz);
-STATIC Lba ke_find_free_catalog(SizeT sz);
-STATIC Lba ke_find_free_data(SizeT sz);
+/// forward decl.
+
+STATIC Lba ke_find_free_fork(SizeT sz, Int32 drv, NewCatalog* catalog);
+STATIC Lba ke_find_free_catalog(SizeT kind, Int32 drv);
STATIC MountpointInterface sMountpointInterface;
@@ -26,7 +29,8 @@ _Output NewFork* NewFSParser::CreateFork(_Input NewCatalog* catalog,
if (catalog && theFork.Name[0] != 0 && theFork.DataSize > 0) {
Lba whereFork = 0;
- theFork.DataOffset = ke_find_free_fork(theFork.DataSize);
+ theFork.DataOffset =
+ ke_find_free_fork(theFork.DataSize, this->fDriveIndex, catalog);
theFork.Flags |= kNewFSFlagCreated;
if (catalog->FirstFork == 0) {
@@ -172,8 +176,10 @@ bool NewFSParser::Format(_Input _Output DriveTrait* drive) {
/// disk isnt faulty and data has been fetched.
if (drive->fPacket.fPacketGood) {
NewPartitionBlock* partBlock = (NewPartitionBlock*)sectorBuf;
+
+ /// check for an empty partition here.
if (partBlock->PartitionName[0] == 0 &&
- rt_string_cmp(partBlock->Ident, kNewFSIdent, kNewFSIdentLen) == 0) {
+ rt_string_cmp(partBlock->Ident, kNewFSIdent, kNewFSIdentLen)) {
/// partition is free and valid.
rt_copy_memory((VoidPtr)kNewFSIdent, (VoidPtr)partBlock->Ident,
@@ -276,23 +282,129 @@ bool NewFSParser::Seek(_Input _Output NewCatalog* catalog, SizeT off) {
/// @return
SizeT NewFSParser::Tell(_Input _Output NewCatalog* catalog) { return 0; }
-/// @brief
-/// @param sz
-/// @return
-STATIC Lba ke_find_free_fork(SizeT sz) { return 0; }
+/// @brief Find a free fork inside the filesystem.
+/// @param sz the size of the fork to set.
+/// @return the valid lba.
+STATIC Lba ke_find_free_fork(SizeT sz, Int32 drv, NewCatalog* catalog) {
+ auto drive = *sMountpointInterface.GetAddressOf(drv);
-/// @brief
-/// @param sz
-/// @return
-STATIC Lba ke_find_free_catalog(SizeT sz) { return 0; }
+ if (drive) {
+ /// prepare packet.
+ bool done = false;
+ bool error = false;
-/// @brief
-/// @param sz
-/// @return
-STATIC Lba ke_find_free_data(SizeT sz) { return 0; }
+ Lba lba = catalog->LastFork;
+
+ while (!done) {
+ Char sectorBuf[kNewFSMinimumSectorSz] = {0};
+
+ drive->fPacket.fPacketContent = sectorBuf;
+ drive->fPacket.fPacketSize = kNewFSMinimumSectorSz;
+ drive->fPacket.fLba = lba;
+
+ drive->fInput(&drive->fPacket);
+
+ if (!drive->fPacket.fPacketGood) {
+ ///! not a lot of choices, disk has become unreliable.
+ if (ke_calculate_crc32(sectorBuf, kNewFSMinimumSectorSz) !=
+ drive->fPacket.fPacketCRC32) {
+ DbgLastError() = kErrorDiskIsCorrupted;
+ }
+
+ error = true;
+ break;
+ }
+
+ NewFork* fork = (NewFork*)sectorBuf;
+
+ if (fork->DataSize == 0 && fork->Name[0] == 0 &&
+ (fork->Flags == kNewFSFlagDeleted ||
+ fork->Flags == kNewFSFlagUnallocated)) {
+ fork->DataSize = sz;
+ fork->Flags |= kNewFSFlagCreated;
+
+ drive->fOutput(&drive->fPacket);
+
+ /// here it's either a read-only filesystem or something bad happened.'
+ if (!drive->fPacket.fPacketGood) {
+ DbgLastError() = kErrorDiskReadOnly;
+
+ return 0;
+ }
+
+ return lba;
+ }
+
+ lba += sizeof(NewFork);
+ }
+
+ if (error) {
+ DbgLastError() = kErrorDisk;
+ return 0;
+ }
+ }
+
+ return 0;
+}
+
+/// @brief find a free catalog.
+/// @param kind the catalog kind.
+/// @return the valid lba.
+STATIC Lba ke_find_free_catalog(SizeT kind, Int32 drv) {
+ auto drive = *sMountpointInterface.GetAddressOf(drv);
+
+ if (drive) {
+ Char sectorBuf[kNewFSMinimumSectorSz] = {0};
+
+ /// prepare packet.
+
+ drive->fPacket.fPacketContent = sectorBuf;
+ drive->fPacket.fPacketSize = kNewFSMinimumSectorSz;
+ drive->fPacket.fLba = kNewFSAddressAsLba;
+
+ drive->fInput(&drive->fPacket);
+
+ NewPartitionBlock* partBlock = (NewPartitionBlock*)sectorBuf;
+
+ /// check for a valid partition.
+ if (partBlock->PartitionName[0] != 0 &&
+ rt_string_cmp(partBlock->Ident, kNewFSIdent, kNewFSIdentLen) == 0) {
+ auto startLba = partBlock->FreeCatalog;
+
+ if (startLba == 0) {
+ DbgLastError() = kErrorDiskIsFull;
+ return 1;
+ } else {
+ while (startLba != 0) {
+ drive->fPacket.fPacketContent = sectorBuf;
+ drive->fPacket.fPacketSize = kNewFSMinimumSectorSz;
+ drive->fPacket.fLba = startLba;
+
+ drive->fInput(&drive->fPacket);
+
+ NewCatalog* catalog = (NewCatalog*)sectorBuf;
+
+ if (catalog->Flags == kNewFSFlagUnallocated ||
+ catalog->Flags == kNewFSFlagDeleted) {
+ catalog->Flags |= kNewFSFlagCreated;
+ catalog->Kind |= kind;
+
+ return startLba;
+ }
+
+ startLba = catalog->NextSibling;
+ }
+
+ return 0;
+ }
+ }
+ }
+
+ return 0;
+}
namespace NewOS::Detail {
-Boolean fs_init_newfs(Void) noexcept { return false; }
+Boolean fs_init_newfs(Void) noexcept { return true; }
} // namespace NewOS::Detail
#endif // ifdef __FSKIT_NEWFS__