feat: vfs - add stat syscall
This commit is contained in:
@@ -12,4 +12,4 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#define MONTAUK_BUILD_NUMBER 2
|
#define MONTAUK_BUILD_NUMBER 4
|
||||||
|
|||||||
@@ -116,6 +116,23 @@ namespace montauk::abi {
|
|||||||
return Fs::Vfs::VfsDelete(resolved);
|
return Fs::Vfs::VfsDelete(resolved);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int Sys_Stat(const char* path, FileStat* out) {
|
||||||
|
if (out == nullptr) return -1;
|
||||||
|
char resolved[256];
|
||||||
|
if (!ResolveProcessPath(path, resolved, sizeof(resolved))) return -1;
|
||||||
|
|
||||||
|
Fs::Vfs::StatInfo info;
|
||||||
|
if (Fs::Vfs::VfsStat(resolved, info) != 0) return -1;
|
||||||
|
|
||||||
|
out->size = info.size;
|
||||||
|
out->mtime = info.mtime;
|
||||||
|
out->ctime = info.ctime;
|
||||||
|
out->atime = info.atime;
|
||||||
|
out->mode = info.mode;
|
||||||
|
out->isDir = info.isDir ? 1u : 0u;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int Sys_FMkdir(const char* path) {
|
static int Sys_FMkdir(const char* path) {
|
||||||
char resolved[256];
|
char resolved[256];
|
||||||
if (!ResolveProcessPath(path, resolved, sizeof(resolved))) return -1;
|
if (!ResolveProcessPath(path, resolved, sizeof(resolved))) return -1;
|
||||||
|
|||||||
@@ -153,6 +153,10 @@ namespace montauk::abi {
|
|||||||
case SYS_GETEXECPATH:
|
case SYS_GETEXECPATH:
|
||||||
if (!UserMemory::Range(frame->arg2 ? frame->arg1 : frame->arg1, frame->arg2, true)) return -1;
|
if (!UserMemory::Range(frame->arg2 ? frame->arg1 : frame->arg1, frame->arg2, true)) return -1;
|
||||||
return Sys_GetExecPath((char*)frame->arg1, frame->arg2);
|
return Sys_GetExecPath((char*)frame->arg1, frame->arg2);
|
||||||
|
case SYS_STAT:
|
||||||
|
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_TERMSIZE:
|
case SYS_TERMSIZE:
|
||||||
return (int64_t)Sys_TermSize();
|
return (int64_t)Sys_TermSize();
|
||||||
case SYS_GETARGS:
|
case SYS_GETARGS:
|
||||||
|
|||||||
@@ -285,6 +285,9 @@ namespace montauk::abi {
|
|||||||
// Absolute path of the running executable (for argv[0]).
|
// Absolute path of the running executable (for argv[0]).
|
||||||
static constexpr uint64_t SYS_GETEXECPATH = 151; // (index, flags) -> new front index; index=-1 queries support (1/0); flags bit0 = wait vsync
|
static constexpr uint64_t SYS_GETEXECPATH = 151; // (index, flags) -> new front index; index=-1 queries support (1/0); flags bit0 = wait vsync
|
||||||
|
|
||||||
|
// Path metadata (size, timestamps, mode). (const char* path, FileStat* out) -> 0, -1 on error/unsupported.
|
||||||
|
static constexpr uint64_t SYS_STAT = 152;
|
||||||
|
|
||||||
// Tunable parameters (for SYS_SDR_SETPARAM / SYS_SDR_GETPARAM).
|
// Tunable parameters (for SYS_SDR_SETPARAM / SYS_SDR_GETPARAM).
|
||||||
static constexpr int SDR_PARAM_FREQ = 0; // center frequency, Hz
|
static constexpr int SDR_PARAM_FREQ = 0; // center frequency, Hz
|
||||||
static constexpr int SDR_PARAM_SAMPLE_RATE = 1; // sample rate, Hz
|
static constexpr int SDR_PARAM_SAMPLE_RATE = 1; // sample rate, Hz
|
||||||
@@ -326,6 +329,17 @@ namespace montauk::abi {
|
|||||||
uint8_t Second;
|
uint8_t Second;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Path metadata returned by SYS_STAT. Timestamps are UTC unix seconds;
|
||||||
|
// a filesystem that does not record a given time reports it as 0.
|
||||||
|
struct FileStat {
|
||||||
|
uint64_t size; // file size in bytes
|
||||||
|
int64_t mtime; // last data modification time
|
||||||
|
int64_t ctime; // last inode (metadata) change time
|
||||||
|
int64_t atime; // last access time
|
||||||
|
uint32_t mode; // ext2/POSIX mode bits (type + permissions)
|
||||||
|
uint32_t isDir; // 1 if the entry is a directory, else 0
|
||||||
|
};
|
||||||
|
|
||||||
struct FbInfo {
|
struct FbInfo {
|
||||||
uint64_t width;
|
uint64_t width;
|
||||||
uint64_t height;
|
uint64_t height;
|
||||||
|
|||||||
@@ -1189,6 +1189,24 @@ namespace Fs::Ext2 {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int StatImpl(int inst, const char* path, Vfs::StatInfo* out) {
|
||||||
|
if (!out) return -1;
|
||||||
|
if (inst < 0 || inst >= g_instanceCount || !g_instances[inst].active) return -1;
|
||||||
|
auto& self = g_instances[inst];
|
||||||
|
|
||||||
|
uint32_t inodeNum;
|
||||||
|
Inode inode;
|
||||||
|
if (!TraversePath(self, path, &inodeNum, &inode)) return -1;
|
||||||
|
|
||||||
|
out->size = inode.i_size;
|
||||||
|
out->mtime = (int64_t)inode.i_mtime;
|
||||||
|
out->ctime = (int64_t)inode.i_ctime;
|
||||||
|
out->atime = (int64_t)inode.i_atime;
|
||||||
|
out->mode = inode.i_mode;
|
||||||
|
out->isDir = (inode.i_mode & IMODE_TYPE_MASK) == IMODE_DIR;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int ReadImpl(int inst, int handle, uint8_t* buffer,
|
static int ReadImpl(int inst, int handle, uint8_t* buffer,
|
||||||
uint64_t offset, uint64_t size) {
|
uint64_t offset, uint64_t size) {
|
||||||
if (inst < 0 || inst >= g_instanceCount) return -1;
|
if (inst < 0 || inst >= g_instanceCount) return -1;
|
||||||
@@ -1764,6 +1782,7 @@ namespace Fs::Ext2 {
|
|||||||
static int Mkdir(const char* p) { return MkdirImpl(N, p); }
|
static int Mkdir(const char* p) { return MkdirImpl(N, p); }
|
||||||
static int Rename(const char* o, const char* n) { return RenameImpl(N, o, n); }
|
static int Rename(const char* o, const char* n) { return RenameImpl(N, o, n); }
|
||||||
static const char* GetLabel() { return GetLabelImpl(N); }
|
static const char* GetLabel() { return GetLabelImpl(N); }
|
||||||
|
static int Stat(const char* p, Vfs::StatInfo* o) { return StatImpl(N, p, o); }
|
||||||
};
|
};
|
||||||
|
|
||||||
template<int N>
|
template<int N>
|
||||||
@@ -1781,6 +1800,7 @@ namespace Fs::Ext2 {
|
|||||||
Thunks<N>::Rename,
|
Thunks<N>::Rename,
|
||||||
Thunks<N>::GetLabel,
|
Thunks<N>::GetLabel,
|
||||||
Thunks<N>::ReadDirAt,
|
Thunks<N>::ReadDirAt,
|
||||||
|
Thunks<N>::Stat,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -288,6 +288,25 @@ namespace Fs::Vfs {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int VfsStat(const char* path, StatInfo& out) {
|
||||||
|
int drive;
|
||||||
|
const char* localPath;
|
||||||
|
|
||||||
|
out = StatInfo{};
|
||||||
|
|
||||||
|
if (!ParsePath(path, drive, localPath)) return -1;
|
||||||
|
if (drive < 0 || drive >= MaxDrives || !driveActive[drive] || driveTable[drive] == nullptr) return -1;
|
||||||
|
if (driveTable[drive]->Stat == nullptr) return -1;
|
||||||
|
|
||||||
|
vfsLock.Acquire();
|
||||||
|
FsDriver* driver = driveTable[drive];
|
||||||
|
int result = (driveActive[drive] && driver && driver->Stat)
|
||||||
|
? driver->Stat(localPath, &out)
|
||||||
|
: -1;
|
||||||
|
vfsLock.Release();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
int VfsMkdir(const char* path) {
|
int VfsMkdir(const char* path) {
|
||||||
int drive;
|
int drive;
|
||||||
const char* localPath;
|
const char* localPath;
|
||||||
|
|||||||
@@ -18,6 +18,17 @@ namespace Fs::Vfs {
|
|||||||
uint32_t generation;
|
uint32_t generation;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Metadata for a single path, filled by FsDriver::Stat. Timestamps are UTC
|
||||||
|
// unix seconds; a filesystem that does not record a given time leaves it 0.
|
||||||
|
struct StatInfo {
|
||||||
|
uint64_t size; // file size in bytes
|
||||||
|
int64_t mtime; // last data modification time
|
||||||
|
int64_t ctime; // last inode (metadata) change time
|
||||||
|
int64_t atime; // last access time
|
||||||
|
uint32_t mode; // ext2/POSIX i_mode bits (type + permissions)
|
||||||
|
bool isDir; // true if the entry is a directory
|
||||||
|
};
|
||||||
|
|
||||||
struct FsDriver {
|
struct FsDriver {
|
||||||
int (*Open)(const char* path);
|
int (*Open)(const char* path);
|
||||||
int (*Read)(int handle, uint8_t* buffer, uint64_t offset, uint64_t size);
|
int (*Read)(int handle, uint8_t* buffer, uint64_t offset, uint64_t size);
|
||||||
@@ -33,6 +44,9 @@ namespace Fs::Vfs {
|
|||||||
// Optional: paginated directory read returning entries [startIndex, startIndex+maxEntries).
|
// Optional: paginated directory read returning entries [startIndex, startIndex+maxEntries).
|
||||||
// Drivers that leave this null are read via ReadDir at startIndex 0 only.
|
// Drivers that leave this null are read via ReadDir at startIndex 0 only.
|
||||||
int (*ReadDirAt)(const char* path, const char** outNames, int maxEntries, int startIndex);
|
int (*ReadDirAt)(const char* path, const char** outNames, int maxEntries, int startIndex);
|
||||||
|
// Optional: fill metadata for a path. Drivers that leave this null do
|
||||||
|
// not support stat and VfsStat returns -1 for their paths.
|
||||||
|
int (*Stat)(const char* path, StatInfo* out);
|
||||||
};
|
};
|
||||||
|
|
||||||
void Initialize();
|
void Initialize();
|
||||||
@@ -51,6 +65,7 @@ namespace Fs::Vfs {
|
|||||||
void CloseBackendFile(BackendFile& file);
|
void CloseBackendFile(BackendFile& file);
|
||||||
|
|
||||||
int VfsDelete(const char* path);
|
int VfsDelete(const char* path);
|
||||||
|
int VfsStat(const char* path, StatInfo& out);
|
||||||
int VfsReadDir(const char* path, const char** outNames, int maxEntries);
|
int VfsReadDir(const char* path, const char** outNames, int maxEntries);
|
||||||
int VfsReadDirAt(const char* path, const char** outNames, int maxEntries, int startIndex);
|
int VfsReadDirAt(const char* path, const char** outNames, int maxEntries, int startIndex);
|
||||||
int VfsMkdir(const char* path);
|
int VfsMkdir(const char* path);
|
||||||
|
|||||||
@@ -209,6 +209,9 @@ namespace montauk::abi {
|
|||||||
// Absolute path of the running executable (for argv[0]).
|
// Absolute path of the running executable (for argv[0]).
|
||||||
static constexpr uint64_t SYS_GETEXECPATH = 151; // (index, flags) -> new front index; index=-1 queries support (1/0); flags bit0 = wait vsync
|
static constexpr uint64_t SYS_GETEXECPATH = 151; // (index, flags) -> new front index; index=-1 queries support (1/0); flags bit0 = wait vsync
|
||||||
|
|
||||||
|
// Path metadata (size, timestamps, mode). (const char* path, FileStat* out) -> 0, -1 on error/unsupported.
|
||||||
|
static constexpr uint64_t SYS_STAT = 152;
|
||||||
|
|
||||||
// Tunable parameters (for SYS_SDR_SETPARAM / SYS_SDR_GETPARAM).
|
// Tunable parameters (for SYS_SDR_SETPARAM / SYS_SDR_GETPARAM).
|
||||||
static constexpr int SDR_PARAM_FREQ = 0; // center frequency, Hz
|
static constexpr int SDR_PARAM_FREQ = 0; // center frequency, Hz
|
||||||
static constexpr int SDR_PARAM_SAMPLE_RATE = 1; // sample rate, Hz
|
static constexpr int SDR_PARAM_SAMPLE_RATE = 1; // sample rate, Hz
|
||||||
@@ -287,6 +290,17 @@ namespace montauk::abi {
|
|||||||
uint8_t Second;
|
uint8_t Second;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Path metadata returned by SYS_STAT. Timestamps are UTC unix seconds;
|
||||||
|
// a filesystem that does not record a given time reports it as 0.
|
||||||
|
struct FileStat {
|
||||||
|
uint64_t size; // file size in bytes
|
||||||
|
int64_t mtime; // last data modification time
|
||||||
|
int64_t ctime; // last inode (metadata) change time
|
||||||
|
int64_t atime; // last access time
|
||||||
|
uint32_t mode; // ext2/POSIX mode bits (type + permissions)
|
||||||
|
uint32_t isDir; // 1 if the entry is a directory, else 0
|
||||||
|
};
|
||||||
|
|
||||||
struct FbInfo {
|
struct FbInfo {
|
||||||
uint64_t width;
|
uint64_t width;
|
||||||
uint64_t height;
|
uint64_t height;
|
||||||
|
|||||||
@@ -175,6 +175,7 @@ extern "C" {
|
|||||||
#define MTK_SYS_POWERINFO 149
|
#define MTK_SYS_POWERINFO 149
|
||||||
#define MTK_SYS_FBFLIP 150
|
#define MTK_SYS_FBFLIP 150
|
||||||
#define MTK_SYS_GETEXECPATH 151
|
#define MTK_SYS_GETEXECPATH 151
|
||||||
|
#define MTK_SYS_STAT 152
|
||||||
/* @SYSCALLS-END */
|
/* @SYSCALLS-END */
|
||||||
|
|
||||||
#define MTK_SOCK_TCP 1
|
#define MTK_SOCK_TCP 1
|
||||||
|
|||||||
@@ -165,6 +165,11 @@ namespace montauk {
|
|||||||
inline int frename(const char* oldPath, const char* newPath) {
|
inline int frename(const char* oldPath, const char* newPath) {
|
||||||
return (int)syscall2(montauk::abi::SYS_FRENAME, (uint64_t)oldPath, (uint64_t)newPath);
|
return (int)syscall2(montauk::abi::SYS_FRENAME, (uint64_t)oldPath, (uint64_t)newPath);
|
||||||
}
|
}
|
||||||
|
// Fill *out with metadata (size, timestamps, mode) for the path.
|
||||||
|
// Returns 0 on success, -1 on error or if the filesystem lacks stat support.
|
||||||
|
inline int stat(const char* path, montauk::abi::FileStat* out) {
|
||||||
|
return (int)syscall2(montauk::abi::SYS_STAT, (uint64_t)path, (uint64_t)out);
|
||||||
|
}
|
||||||
inline int drivelist(int* outDrives, int max) {
|
inline int drivelist(int* outDrives, int max) {
|
||||||
return (int)syscall2(montauk::abi::SYS_DRIVELIST, (uint64_t)outDrives, (uint64_t)max);
|
return (int)syscall2(montauk::abi::SYS_DRIVELIST, (uint64_t)outDrives, (uint64_t)max);
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user