feat: Rust std target + ruststd tests; SYS_EXIT_GROUP; fix mkdir/create under missing parent
This commit is contained in:
1 parent
9e66c3b249
commit
e87bd358a6
20 files changed
+657
-97
No files matched your search
@@ -12,4 +12,4 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#define MONTAUK_BUILD_NUMBER 1
|
||||
#define MONTAUK_BUILD_NUMBER 3
|
||||
@@ -27,6 +27,23 @@ namespace montauk::abi {
|
||||
return required == 0 || Sched::HasCapability(required);
|
||||
}
|
||||
|
||||
// Drivers fail a create under a missing parent with a bare -1; report it
|
||||
// as NoSuchPath so callers can tell it apart (Rust's create_dir_all only
|
||||
// creates the missing ancestors when mkdir says NotFound).
|
||||
static bool ParentDirExists(const char* resolved) {
|
||||
char parent[256];
|
||||
int len = Lib::strlen(resolved);
|
||||
if (len >= (int)sizeof(parent)) return false;
|
||||
memcpy(parent, resolved, len + 1);
|
||||
while (len > 0 && parent[len - 1] == '/') len--;
|
||||
while (len > 0 && parent[len - 1] != '/') len--;
|
||||
while (len > 0 && parent[len - 1] == '/') len--;
|
||||
if (len == 0 || parent[len - 1] == ':') return true; // drive root
|
||||
parent[len] = '\0';
|
||||
Fs::Vfs::StatInfo info;
|
||||
return Fs::Vfs::VfsStat(parent, info) == 0 && info.isDir;
|
||||
}
|
||||
|
||||
static int Sys_Open(const char* path) {
|
||||
char resolved[256];
|
||||
if (!ResolveProcessPath(path, resolved, sizeof(resolved))) return InvalidArgument;
|
||||
@@ -117,6 +134,7 @@ namespace montauk::abi {
|
||||
char resolved[256];
|
||||
if (!ResolveProcessPath(path, resolved, sizeof(resolved))) return InvalidArgument;
|
||||
if (!CanModifyFilePath(resolved)) return SystemIntegrityError;
|
||||
if (!ParentDirExists(resolved)) return NoSuchPath;
|
||||
return Ipc::CreateFileHandle(resolved);
|
||||
}
|
||||
|
||||
@@ -171,6 +189,7 @@ namespace montauk::abi {
|
||||
char resolved[256];
|
||||
if (!ResolveProcessPath(path, resolved, sizeof(resolved))) return InvalidArgument;
|
||||
if (!CanModifyFilePath(resolved)) return SystemIntegrityError;
|
||||
if (!ParentDirExists(resolved)) return NoSuchPath;
|
||||
return Fs::Vfs::VfsMkdir(resolved);
|
||||
}
|
||||
|
||||
|
||||
@@ -228,6 +228,14 @@ namespace montauk::abi {
|
||||
Sched::ExitProcess();
|
||||
}
|
||||
|
||||
// Like Sys_Abort, but a normal exit with the caller's code: every thread
|
||||
// goes, and waiters see exitCode & 0xFF, the same as SYS_EXIT on the main
|
||||
// thread.
|
||||
static void Sys_ExitGroup(int exitCode) {
|
||||
Sched::KillProcess(Sched::GetCurrentPid(), exitCode & 0xFF);
|
||||
Sched::ExitProcess();
|
||||
}
|
||||
|
||||
static int Sys_Kill(int pid) {
|
||||
// A process may always kill itself (kill(getpid(), ...)); waiters
|
||||
// see TerminatedKilled. abort() uses SYS_ABORT instead.
|
||||
|
||||
@@ -403,6 +403,9 @@ namespace montauk::abi {
|
||||
case SYS_ABORT:
|
||||
Sys_Abort();
|
||||
return Success;
|
||||
case SYS_EXIT_GROUP:
|
||||
Sys_ExitGroup((int)frame->arg1);
|
||||
return Success;
|
||||
case SYS_SETSESSION:
|
||||
return (int64_t)Sys_SetSession();
|
||||
case SYS_KILLSESSION:
|
||||
|
||||
@@ -380,6 +380,12 @@ namespace montauk::abi {
|
||||
sibling thread ends only that thread, so abort() needs its own call. */
|
||||
static constexpr uint64_t SYS_ABORT = 198; // () -> does not return
|
||||
|
||||
/* Normal termination of the whole process from any thread, with an exit
|
||||
code (0..255) instead of SYS_ABORT's fixed TerminatedAborted. libc
|
||||
exit() and Rust std::process::exit() use it, so exiting from a sibling
|
||||
thread ends the process rather than only that thread. */
|
||||
static constexpr uint64_t SYS_EXIT_GROUP = 199; // (exitCode) -> does not return
|
||||
|
||||
/* Kernel-owned process capabilities. User identities may namespace
|
||||
per-user resources, but never participate in authorization decisions. */
|
||||
static constexpr uint64_t CAP_PROCESS_ADMIN = 1ULL << 0;
|
||||
|
||||
@@ -89,6 +89,20 @@ namespace Fs::Ramdisk {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Mkdir/Create must not conjure entries under a missing parent: the
|
||||
// table is flat, so "a/b/" with no "a/" entry is invisible to ReadDir of
|
||||
// the parent and makes "a" fail Stat, Delete and recursive removal.
|
||||
static bool ParentExists(const char* path) {
|
||||
char normalized[MaxNameLen];
|
||||
int len = NormalizePath(path, normalized, MaxNameLen);
|
||||
if (len < 0) return false;
|
||||
while (len > 0 && normalized[len - 1] != '/') len--;
|
||||
if (len <= 1) return true; // parent is the root
|
||||
normalized[len - 1] = '\0';
|
||||
int idx = FindEntryByPath(normalized);
|
||||
return idx >= 0 && fileTable[idx].isDirectory;
|
||||
}
|
||||
|
||||
void Initialize(void* moduleData, uint64_t moduleSize) {
|
||||
Kt::KernelLogStream(Kt::OK, "Ramdisk") << "Parsing USTAR archive (" << moduleSize << " bytes)";
|
||||
|
||||
@@ -442,6 +456,8 @@ namespace Fs::Ramdisk {
|
||||
}
|
||||
}
|
||||
|
||||
if (!ParentExists(path)) return -1;
|
||||
|
||||
// Create new file entry
|
||||
FileEntry& entry = fileTable[fileCount];
|
||||
|
||||
@@ -531,6 +547,8 @@ namespace Fs::Ramdisk {
|
||||
}
|
||||
}
|
||||
|
||||
if (!ParentExists(path)) return -1;
|
||||
|
||||
// Create directory entry (stored with trailing slash for tar convention)
|
||||
FileEntry& entry = fileTable[fileCount];
|
||||
|
||||
|
||||
Reference in new issue
Block a user