From 5c02c5fe790179e5c2cd5014dd7db0bed846c1cb Mon Sep 17 00:00:00 2001 From: Daniel Hammer Date: Tue, 21 Jul 2026 14:09:17 +0200 Subject: [PATCH] feat: ext2 - save timestamp metadata --- kernel/src/Api/BuildNo.hpp | 2 +- kernel/src/Fs/Ext2.cpp | 68 ++++++++++++++++++++++++++++++++++++-- 2 files changed, 67 insertions(+), 3 deletions(-) diff --git a/kernel/src/Api/BuildNo.hpp b/kernel/src/Api/BuildNo.hpp index 47643ad..b9758b0 100644 --- a/kernel/src/Api/BuildNo.hpp +++ b/kernel/src/Api/BuildNo.hpp @@ -12,4 +12,4 @@ #pragma once -#define MONTAUK_BUILD_NUMBER 1 +#define MONTAUK_BUILD_NUMBER 2 diff --git a/kernel/src/Fs/Ext2.cpp b/kernel/src/Fs/Ext2.cpp index 81083a7..0b44208 100644 --- a/kernel/src/Fs/Ext2.cpp +++ b/kernel/src/Fs/Ext2.cpp @@ -10,6 +10,7 @@ #include #include #include +#include using namespace Kt; @@ -261,6 +262,15 @@ namespace Fs::Ext2 { return WriteBlock(inst, inodeTableBlock + blockOffset, inst.blockBuf); } + // Current wall-clock time as an ext2 timestamp (UTC unix seconds, 32-bit). + // Returns 0 before timekeeping is initialized so we never write a bogus + // date; a zero timestamp is the same "unknown" value ext2 already tolerates. + static uint32_t Ext2Now() { + int64_t ts = Timekeeping::GetUnixTimestamp(); + if (ts < 0) ts = 0; + return (uint32_t)ts; + } + // ========================================================================= // Block addressing — resolve logical block index to physical block number // ========================================================================= @@ -1320,6 +1330,9 @@ namespace Fs::Ext2 { // Write updated inode to disk if (bytesWritten > 0) { + uint32_t now = Ext2Now(); + file.inode.i_mtime = now; + file.inode.i_ctime = now; WriteInode(self, file.inodeNum, &file.inode); } @@ -1353,6 +1366,9 @@ namespace Fs::Ext2 { FreeInodeBlocks(self, existInode); existInode.i_size = 0; existInode.i_blocks = 0; + uint32_t now = Ext2Now(); + existInode.i_mtime = now; + existInode.i_ctime = now; WriteInode(self, existing.inodeNum, &existInode); // Open a handle @@ -1378,6 +1394,10 @@ namespace Fs::Ext2 { memset(&newInode, 0, sizeof(Inode)); newInode.i_mode = IMODE_REG | 0644; // regular file, rw-r--r-- newInode.i_links_count = 1; + uint32_t nowTs = Ext2Now(); + newInode.i_atime = nowTs; + newInode.i_ctime = nowTs; + newInode.i_mtime = nowTs; WriteInode(self, newInodeNum, &newInode); // Add directory entry @@ -1387,6 +1407,14 @@ namespace Fs::Ext2 { return -1; } + // Parent directory's contents changed; bump its mtime/ctime. + // Re-read first since AddDirEntry may have grown the parent inode. + if (ReadInode(self, parentInodeNum, &parentInode)) { + parentInode.i_mtime = nowTs; + parentInode.i_ctime = nowTs; + WriteInode(self, parentInodeNum, &parentInode); + } + // Open a handle for (int i = 0; i < MaxFilesPerInstance; i++) { if (!self.files[i].inUse) { @@ -1432,19 +1460,26 @@ namespace Fs::Ext2 { // Remove directory entry if (!RemoveDirEntry(self, parentInode, fileName)) return -1; + uint32_t now = Ext2Now(); + + // Parent directory's contents changed + parentInode.i_mtime = now; + parentInode.i_ctime = now; // If we deleted a subdirectory, decrement parent's link count (for "..") if (isDir) { parentInode.i_links_count--; - WriteInode(self, parentInodeNum, &parentInode); } + WriteInode(self, parentInodeNum, &parentInode); // Decrement link count targetInode.i_links_count--; if (isDir) targetInode.i_links_count--; // account for "." self-link + targetInode.i_ctime = now; if (targetInode.i_links_count <= 0) { // Free all blocks and the inode FreeInodeBlocks(self, targetInode); targetInode.i_mode = 0; + targetInode.i_dtime = now; WriteInode(self, existing.inodeNum, &targetInode); FreeInode(self, existing.inodeNum); } else { @@ -1535,6 +1570,10 @@ namespace Fs::Ext2 { newInode.i_blocks = blockSize / 512; newInode.i_links_count = 2; // . and parent's entry newInode.i_block[0] = dirBlock; + uint32_t dirNowTs = Ext2Now(); + newInode.i_atime = dirNowTs; + newInode.i_ctime = dirNowTs; + newInode.i_mtime = dirNowTs; WriteInode(self, newInodeNum, &newInode); // Add entry to parent directory @@ -1547,8 +1586,11 @@ namespace Fs::Ext2 { return -1; } - // Increment parent's link count (for ".." in the new dir) + // Increment parent's link count (for ".." in the new dir) and record + // that its contents changed. parentInode.i_links_count++; + parentInode.i_mtime = dirNowTs; + parentInode.i_ctime = dirNowTs; WriteInode(self, parentInodeNum, &parentInode); // Update used_dirs_count in block group descriptor @@ -1675,6 +1717,28 @@ namespace Fs::Ext2 { // TODO: update ".." entry inside the moved directory to point to new parent } + uint32_t now = Ext2Now(); + + // A rename changes the moved inode's ctime (metadata changed). + Inode movedInode; + if (ReadInode(self, oldEntry.inodeNum, &movedInode)) { + movedInode.i_ctime = now; + WriteInode(self, oldEntry.inodeNum, &movedInode); + } + + // Both affected directories had their contents change. + if (ReadInode(self, oldParentInodeNum, &oldParentInode)) { + oldParentInode.i_mtime = now; + oldParentInode.i_ctime = now; + WriteInode(self, oldParentInodeNum, &oldParentInode); + } + if (newParentInodeNum != oldParentInodeNum && + ReadInode(self, newParentInodeNum, &newParentInode)) { + newParentInode.i_mtime = now; + newParentInode.i_ctime = now; + WriteInode(self, newParentInodeNum, &newParentInode); + } + return 0; }