feat: implement utime libc function, SYS_UTIME syscall, filesystem support (ext2 only)
This commit is contained in:
@@ -12,4 +12,4 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#define MONTAUK_BUILD_NUMBER 94
|
||||
#define MONTAUK_BUILD_NUMBER 95
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <Memory/Paging.hpp>
|
||||
#include <Libraries/Memory.hpp>
|
||||
#include <Ipc/Ipc.hpp>
|
||||
#include <Timekeeping/Time.hpp>
|
||||
#include "Path.hpp"
|
||||
|
||||
namespace montauk::abi {
|
||||
@@ -133,6 +134,18 @@ namespace montauk::abi {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int Sys_Utime(const char* path, int64_t atime, int64_t mtime,
|
||||
bool useCurrent) {
|
||||
char resolved[256];
|
||||
if (!ResolveProcessPath(path, resolved, sizeof(resolved))) return -1;
|
||||
if (useCurrent) {
|
||||
int64_t now = Timekeeping::GetUnixTimestamp();
|
||||
atime = now;
|
||||
mtime = now;
|
||||
}
|
||||
return Fs::Vfs::VfsSetTimes(resolved, atime, mtime);
|
||||
}
|
||||
|
||||
static int Sys_FMkdir(const char* path) {
|
||||
char resolved[256];
|
||||
if (!ResolveProcessPath(path, resolved, sizeof(resolved))) return -1;
|
||||
|
||||
@@ -174,6 +174,12 @@ namespace montauk::abi {
|
||||
if (!UserMemory::String(frame->arg1, kMaxPathBytes)) return -1;
|
||||
if (!UserMemory::Writable<FileStat>(frame->arg2)) return -1;
|
||||
return (int64_t)Sys_Stat((const char*)frame->arg1, (FileStat*)frame->arg2);
|
||||
case SYS_UTIME:
|
||||
if (!UserMemory::String(frame->arg1, kMaxPathBytes)) return -1;
|
||||
return (int64_t)Sys_Utime((const char*)frame->arg1,
|
||||
(int64_t)frame->arg2,
|
||||
(int64_t)frame->arg3,
|
||||
frame->arg4 != 0);
|
||||
case SYS_TERMSIZE:
|
||||
return (int64_t)Sys_TermSize();
|
||||
case SYS_GETARGS:
|
||||
|
||||
@@ -310,6 +310,9 @@ namespace montauk::abi {
|
||||
/* Keyboard.hpp */
|
||||
static constexpr uint64_t SYS_GETCHAR_NB = 166; // () -> ascii, 0 if nothing pending; never blocks
|
||||
|
||||
// Set path access/modification times. (path, atime, mtime, useCurrent)
|
||||
static constexpr uint64_t SYS_UTIME = 167;
|
||||
|
||||
// Tunable parameters (for SYS_SDR_SETPARAM / SYS_SDR_GETPARAM).
|
||||
static constexpr int SDR_PARAM_FREQ = 0; // center frequency, Hz
|
||||
static constexpr int SDR_PARAM_SAMPLE_RATE = 1; // sample rate, Hz
|
||||
|
||||
@@ -101,6 +101,7 @@ namespace Fs {
|
||||
.GetLabel = RdGetLabel,
|
||||
.ReadDirAt = RdReadDirAt,
|
||||
.Stat = RdStat,
|
||||
.SetTimes = nullptr,
|
||||
// Statically allocated: nothing to release.
|
||||
.Unmount = nullptr,
|
||||
};
|
||||
|
||||
@@ -1234,6 +1234,31 @@ namespace Fs::Ext2 {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int SetTimesImpl(int inst, const char* path, int64_t atime, int64_t mtime) {
|
||||
if (InstanceAt(inst) == nullptr) return -4;
|
||||
if (atime < 0 || atime > 0xFFFFFFFFLL ||
|
||||
mtime < 0 || mtime > 0xFFFFFFFFLL) return -3;
|
||||
auto& self = g_instances[inst];
|
||||
|
||||
uint32_t inodeNum;
|
||||
Inode inode;
|
||||
if (!TraversePath(self, path, &inodeNum, &inode)) return -1;
|
||||
|
||||
inode.i_atime = (uint32_t)atime;
|
||||
inode.i_mtime = (uint32_t)mtime;
|
||||
inode.i_ctime = Ext2Now();
|
||||
if (!WriteInode(self, inodeNum, &inode)) return -4;
|
||||
|
||||
// Open files cache their inode. Keep every alias coherent so a later
|
||||
// write through an existing handle cannot restore stale metadata.
|
||||
for (int i = 0; i < MaxFilesPerInstance; i++) {
|
||||
if (self.files[i].inUse && self.files[i].inodeNum == inodeNum) {
|
||||
self.files[i].inode = inode;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ReadImpl(int inst, int handle, uint8_t* buffer,
|
||||
uint64_t offset, uint64_t size) {
|
||||
if (InstanceAt(inst) == nullptr) return -1;
|
||||
@@ -1830,6 +1855,7 @@ namespace Fs::Ext2 {
|
||||
static int DrvRename(void* c, const char* o, const char* n) { return RenameImpl(CtxToInst(c), o, n); }
|
||||
static const char* DrvGetLabel(void* c) { return GetLabelImpl(CtxToInst(c)); }
|
||||
static int DrvStat(void* c, const char* p, Vfs::StatInfo* o) { return StatImpl(CtxToInst(c), p, o); }
|
||||
static int DrvSetTimes(void* c, const char* p, int64_t a, int64_t m) { return SetTimesImpl(CtxToInst(c), p, a, m); }
|
||||
|
||||
// Release everything the mount owns. The driver is either not registered
|
||||
// yet, or the VFS has deactivated its drive and drained dispatches.
|
||||
@@ -2040,6 +2066,7 @@ namespace Fs::Ext2 {
|
||||
.GetLabel = DrvGetLabel,
|
||||
.ReadDirAt = DrvReadDirAt,
|
||||
.Stat = DrvStat,
|
||||
.SetTimes = DrvSetTimes,
|
||||
.Unmount = DrvUnmount,
|
||||
};
|
||||
|
||||
|
||||
@@ -2099,6 +2099,7 @@ namespace Fs::Fat32 {
|
||||
.GetLabel = DrvGetLabel,
|
||||
.ReadDirAt = DrvReadDirAt,
|
||||
.Stat = DrvStat,
|
||||
.SetTimes = nullptr,
|
||||
.Unmount = DrvUnmount,
|
||||
};
|
||||
|
||||
|
||||
@@ -307,6 +307,21 @@ namespace Fs::Vfs {
|
||||
return result;
|
||||
}
|
||||
|
||||
int VfsSetTimes(const char* path, int64_t atime, int64_t mtime) {
|
||||
int drive;
|
||||
const char* localPath;
|
||||
|
||||
if (!ParsePath(path, drive, localPath)) return -1;
|
||||
|
||||
vfsLock.Acquire();
|
||||
FsDriver* driver = DriverForLocked(drive);
|
||||
int result = (driver != nullptr && driver->SetTimes != nullptr)
|
||||
? driver->SetTimes(driver->ctx, localPath, atime, mtime)
|
||||
: -2;
|
||||
vfsLock.Release();
|
||||
return result;
|
||||
}
|
||||
|
||||
int VfsMkdir(const char* path) {
|
||||
int drive;
|
||||
const char* localPath;
|
||||
|
||||
@@ -65,6 +65,10 @@ namespace Fs::Vfs {
|
||||
// Optional: fill metadata for a path. Drivers that leave this null do
|
||||
// not support stat and VfsStat returns -1 for their paths.
|
||||
int (*Stat)(void* ctx, const char* path, StatInfo* out);
|
||||
// Optional: set access and modification times for a path. Return 0 on
|
||||
// success, -1 for a missing path, -3 for an unrepresentable time, or
|
||||
// -4 for an I/O error. A null hook yields -2 (unsupported).
|
||||
int (*SetTimes)(void* ctx, const char* path, int64_t atime, int64_t mtime);
|
||||
// Optional: release everything this mount owns, including the FsDriver
|
||||
// itself. Called either when registration fails, before the driver has
|
||||
// become reachable, or by UnregisterDrive once the slot is deactivated
|
||||
@@ -90,6 +94,7 @@ namespace Fs::Vfs {
|
||||
|
||||
int VfsDelete(const char* path);
|
||||
int VfsStat(const char* path, StatInfo& out);
|
||||
int VfsSetTimes(const char* path, int64_t atime, int64_t mtime);
|
||||
int VfsReadDir(const char* path, const char** outNames, int maxEntries);
|
||||
int VfsReadDirAt(const char* path, const char** outNames, int maxEntries, int startIndex);
|
||||
int VfsMkdir(const char* path);
|
||||
|
||||
Reference in New Issue
Block a user