feat: add cwd tracking to kernel, remove shell hack, update system utilities to use getcwd, fix tcc libc stub, fix nonexistent directory issue

This commit is contained in:
2026-03-25 15:45:22 +01:00
parent 9c9a0a9712
commit ea087769f5
22 changed files with 389 additions and 265 deletions
+23 -7
View File
@@ -12,10 +12,13 @@
#include <Memory/HHDM.hpp>
#include <Memory/Paging.hpp>
#include <Libraries/Memory.hpp>
#include "Path.hpp"
namespace Montauk {
static int Sys_Open(const char* path) {
return Fs::Vfs::VfsOpen(path);
char resolved[256];
if (!ResolveProcessPath(path, resolved, sizeof(resolved))) return -1;
return Fs::Vfs::VfsOpen(resolved);
}
static int Sys_Read(int handle, uint8_t* buffer, uint64_t offset, uint64_t size) {
@@ -31,11 +34,14 @@ namespace Montauk {
}
static int Sys_ReadDir(const char* path, const char** outNames, int maxEntries) {
char resolved[256];
if (!ResolveProcessPath(path, resolved, sizeof(resolved))) return -1;
// Get entries from VFS into a kernel-local array
const char* kernelNames[256];
int max = maxEntries;
if (max > 256) max = 256;
int count = Fs::Vfs::VfsReadDir(path, kernelNames, max);
int count = Fs::Vfs::VfsReadDir(resolved, kernelNames, max);
if (count <= 0) return count;
// Allocate a user-accessible page for string data via process heap
@@ -70,22 +76,32 @@ namespace Montauk {
}
static int Sys_FCreate(const char* path) {
return Fs::Vfs::VfsCreate(path);
char resolved[256];
if (!ResolveProcessPath(path, resolved, sizeof(resolved))) return -1;
return Fs::Vfs::VfsCreate(resolved);
}
static int Sys_FDelete(const char* path) {
return Fs::Vfs::VfsDelete(path);
char resolved[256];
if (!ResolveProcessPath(path, resolved, sizeof(resolved))) return -1;
return Fs::Vfs::VfsDelete(resolved);
}
static int Sys_FMkdir(const char* path) {
return Fs::Vfs::VfsMkdir(path);
char resolved[256];
if (!ResolveProcessPath(path, resolved, sizeof(resolved))) return -1;
return Fs::Vfs::VfsMkdir(resolved);
}
static int Sys_FRename(const char* oldPath, const char* newPath) {
return Fs::Vfs::VfsRename(oldPath, newPath);
char resolvedOld[256];
char resolvedNew[256];
if (!ResolveProcessPath(oldPath, resolvedOld, sizeof(resolvedOld))) return -1;
if (!ResolveProcessPath(newPath, resolvedNew, sizeof(resolvedNew))) return -1;
return Fs::Vfs::VfsRename(resolvedOld, resolvedNew);
}
static int Sys_DriveList(int* outDrives, int maxEntries) {
return Fs::Vfs::VfsDriveList(outDrives, maxEntries);
}
};
};
+5 -1
View File
@@ -11,11 +11,15 @@
#include "Syscall.hpp"
#include "Common.hpp"
#include "Path.hpp"
namespace Montauk {
static int Sys_SpawnRedir(const char* path, const char* args) {
int childPid = Sched::Spawn(path, args);
char resolved[256];
if (!ResolveProcessPath(path, resolved, sizeof(resolved))) return -1;
int childPid = Sched::Spawn(resolved, args);
if (childPid < 0) return -1;
auto* child = Sched::GetProcessByPid(childPid);
+143
View File
@@ -0,0 +1,143 @@
/*
* Path.hpp
* Per-process working-directory path resolution helpers
* Copyright (c) 2026 Daniel Hammer
*/
#pragma once
#include <cstddef>
#include <Sched/Scheduler.hpp>
#include <Libraries/Memory.hpp>
namespace Montauk {
static int ParseDrivePrefix(const char* path, int* outPrefixLen = nullptr) {
if (path == nullptr || path[0] < '0' || path[0] > '9') return -1;
int drive = 0;
int i = 0;
while (path[i] >= '0' && path[i] <= '9') {
drive = drive * 10 + (path[i] - '0');
i++;
}
if (path[i] != ':') return -1;
if (outPrefixLen) *outPrefixLen = i + 1;
return drive;
}
static int WriteDriveRoot(char* out, int outMax, int drive) {
if (out == nullptr || outMax < 4 || drive < 0) return -1;
char digits[12];
int digitCount = 0;
do {
digits[digitCount++] = (char)('0' + (drive % 10));
drive /= 10;
} while (drive > 0 && digitCount < (int)sizeof(digits));
if (digitCount + 2 >= outMax) return -1;
int len = 0;
for (int i = digitCount - 1; i >= 0; i--) out[len++] = digits[i];
out[len++] = ':';
out[len++] = '/';
out[len] = '\0';
return len;
}
static bool AppendPathSegment(char* out, int outMax, int& len, int rootLen,
int* segmentBases, int& segmentCount,
const char* segment, int segmentLen) {
if (segmentLen <= 0) return true;
if (segmentLen == 1 && segment[0] == '.') return true;
if (segmentLen == 2 && segment[0] == '.' && segment[1] == '.') {
if (segmentCount > 0) {
len = segmentBases[--segmentCount];
out[len] = '\0';
}
return true;
}
if (segmentCount >= 64) return false;
int baseLen = len;
if (len > rootLen) {
if (len >= outMax - 1) return false;
out[len++] = '/';
}
if (len + segmentLen >= outMax) return false;
memcpy(out + len, segment, (std::size_t)segmentLen);
len += segmentLen;
out[len] = '\0';
segmentBases[segmentCount++] = baseLen;
return true;
}
static bool NormalizePathInto(char* out, int outMax, int& len, int rootLen,
int* segmentBases, int& segmentCount,
const char* path) {
const char* segmentStart = path;
for (const char* p = path;; ++p) {
if (*p == '/' || *p == '\0') {
if (!AppendPathSegment(out, outMax, len, rootLen, segmentBases,
segmentCount, segmentStart, (int)(p - segmentStart))) {
return false;
}
if (*p == '\0') break;
segmentStart = p + 1;
}
}
return true;
}
static bool ResolvePathAgainst(const char* cwd, const char* path, char* out, int outMax) {
if (cwd == nullptr || path == nullptr || out == nullptr || outMax < 4 || path[0] == '\0') return false;
int drive = -1;
int inputPrefixLen = 0;
const char* remainder = path;
bool useCwdBase = false;
drive = ParseDrivePrefix(path, &inputPrefixLen);
if (drive >= 0) {
remainder = path + inputPrefixLen;
if (*remainder == '/') remainder++;
} else if (path[0] == '/') {
drive = ParseDrivePrefix(cwd);
if (drive < 0) return false;
remainder = path + 1;
} else {
drive = ParseDrivePrefix(cwd);
if (drive < 0) return false;
useCwdBase = true;
}
int segmentBases[64];
int segmentCount = 0;
int len = WriteDriveRoot(out, outMax, drive);
if (len < 0) return false;
int rootLen = len;
if (useCwdBase) {
int cwdPrefixLen = 0;
if (ParseDrivePrefix(cwd, &cwdPrefixLen) < 0) return false;
const char* cwdRemainder = cwd + cwdPrefixLen;
if (*cwdRemainder == '/') cwdRemainder++;
if (!NormalizePathInto(out, outMax, len, rootLen, segmentBases, segmentCount, cwdRemainder)) {
return false;
}
}
return NormalizePathInto(out, outMax, len, rootLen, segmentBases, segmentCount, remainder);
}
static bool ResolveProcessPath(const char* path, char* out, int outMax) {
auto* proc = Sched::GetCurrentProcessPtr();
const char* cwd = (proc && proc->cwd[0]) ? proc->cwd : "0:/";
return ResolvePathAgainst(cwd, path, out, outMax);
}
}
+49 -2
View File
@@ -11,9 +11,11 @@
#include <Memory/Paging.hpp>
#include <Memory/PageFrameAllocator.hpp>
#include <Memory/HHDM.hpp>
#include <Fs/Vfs.hpp>
#include "Syscall.hpp"
#include "WinServer.hpp"
#include "Path.hpp"
namespace Montauk {
static void Sys_Exit(int exitCode) {
@@ -38,8 +40,11 @@ namespace Montauk {
}
static int Sys_Spawn(const char* path, const char* args) {
char resolved[256];
if (!ResolveProcessPath(path, resolved, sizeof(resolved))) return -1;
auto* parent = Sched::GetCurrentProcessPtr();
int childPid = Sched::Spawn(path, args);
int childPid = Sched::Spawn(resolved, args);
if (childPid < 0) return childPid;
// Inherit I/O redirection: if the parent is redirected, the child
@@ -120,4 +125,46 @@ namespace Montauk {
buf[i] = '\0';
return i;
}
};
static int Sys_GetCwd(char* buf, uint64_t maxLen) {
auto* proc = Sched::GetCurrentProcessPtr();
if (proc == nullptr || buf == nullptr || maxLen == 0) return -1;
const char* cwd = proc->cwd[0] ? proc->cwd : "0:/";
int i = 0;
for (; i < (int)maxLen - 1 && cwd[i]; i++) buf[i] = cwd[i];
buf[i] = '\0';
return i;
}
static int Sys_Chdir(const char* path) {
auto* proc = Sched::GetCurrentProcessPtr();
if (proc == nullptr || path == nullptr) return -1;
char resolved[256];
if (!ResolveProcessPath(path, resolved, sizeof(resolved))) return -1;
bool isDriveRoot = false;
{
int prefixLen = 0;
if (ParseDrivePrefix(resolved, &prefixLen) >= 0 &&
resolved[prefixLen] == '/' && resolved[prefixLen + 1] == '\0') {
isDriveRoot = true;
}
}
if (isDriveRoot) {
const char* entries[1];
if (Fs::Vfs::VfsReadDir(resolved, entries, 1) < 0) return -1;
} else {
int handle = Fs::Vfs::VfsOpen(resolved);
if (handle < 0) return -1;
Fs::Vfs::VfsClose(handle);
}
int i = 0;
for (; i < 255 && resolved[i]; i++) proc->cwd[i] = resolved[i];
proc->cwd[i] = '\0';
return 0;
}
};
+6
View File
@@ -347,6 +347,12 @@ namespace Montauk {
case SYS_GETUSER:
if (!ValidUserPtr(frame->arg1)) return -1;
return Sys_GetUser((char*)frame->arg1, frame->arg2);
case SYS_GETCWD:
if (!ValidUserPtr(frame->arg1)) return -1;
return Sys_GetCwd((char*)frame->arg1, frame->arg2);
case SYS_CHDIR:
if (!ValidUserPtr(frame->arg1)) return -1;
return Sys_Chdir((const char*)frame->arg1);
default:
return -1;
}
+2
View File
@@ -184,6 +184,8 @@ namespace Montauk {
/* Filesystem.hpp */
static constexpr uint64_t SYS_FRENAME = 94;
static constexpr uint64_t SYS_GETCWD = 95;
static constexpr uint64_t SYS_CHDIR = 96;
static constexpr int SOCK_TCP = 1;
static constexpr int SOCK_UDP = 2;