feat: extend syscall

This commit is contained in:
dualfroz committed 2026-09-08 17:02:10 +02:00
1 parent 5149adf7ae
commit 643fa45f6a
1 file changed
+80 -2
+80 -2
View File
@@ -298,9 +298,25 @@ uint64 syscallDispatch(Registers* regs)
}
regs->rax = (uint64)result;
return (uint64)regs;
case sysRead:
regs->rax = (uint64)doRead(regs->rdi, regs->rsi, regs->rdx);
}
case sysRead: {
int64 result = doRead(regs->rdi, regs->rsi, regs->rdx);
if (result == -1) {
/* Covers a fdFlagBlocking pipe/fifo end (see sysWrite above) and
fd 0's console reader queue (keyboard.h) alike -- both report
"would block" as -1 from doRead, and vfsBlockingChannel picks
the right wait channel for whichever kind fd actually is. */
const void* channel = vfsBlockingChannel((int)regs->rdi, false);
if (channel) {
currentThread()->sigInRetryableSyscall = true;
schedBlockCurrent(channel);
regs->rip -= 2;
return schedule((uint64)regs);
}
}
regs->rax = (uint64)result;
return (uint64)regs;
}
case sysGetpid:
regs->rax = currentThreadId();
return (uint64)regs;
@@ -358,6 +374,68 @@ uint64 syscallDispatch(Registers* regs)
regs->rax = (uint64)(int64)vfsMkdir(path);
return (uint64)regs;
}
case sysChdir: {
char path[256];
if (!copyUserPath(regs->rdi, path, sizeof(path)))
regs->rax = (uint64)-1;
else
regs->rax = (uint64)(int64)vfsChdir(path);
return (uint64)regs;
}
case sysGetcwd:
if (!userRangeOk(regs->rdi, regs->rsi))
regs->rax = (uint64)-1;
else
regs->rax = (uint64)vfsGetcwd((char*)regs->rdi, regs->rsi);
return (uint64)regs;
case sysGetEnv: {
char name[envEntryMax];
if (!copyUserPath(regs->rdi, name, sizeof(name)) || !userRangeOk(regs->rsi, regs->rdx)) {
regs->rax = (uint64)-1;
return (uint64)regs;
}
const char* value = currentThreadGetEnv(name);
if (!value) {
regs->rax = (uint64)-1;
return (uint64)regs;
}
uint64 len = strlen(value);
if (len >= regs->rdx) {
regs->rax = (uint64)-1;
return (uint64)regs;
}
memcpy((void*)regs->rsi, value, len + 1);
regs->rax = (uint64)len;
return (uint64)regs;
}
case sysSetEnv: {
char name[envEntryMax];
char value[envEntryMax];
if (!copyUserPath(regs->rdi, name, sizeof(name)) ||
!copyUserPath(regs->rsi, value, sizeof(value))) {
regs->rax = (uint64)-1;
return (uint64)regs;
}
regs->rax = currentThreadSetEnv(name, value) ? 0 : (uint64)-1;
return (uint64)regs;
}
case sysUnsetEnv: {
/* Real unsetenv(3): a no-op success whether or not `name` actually
had an entry -- ONLY a bad user pointer/path is a real failure
here, unlike sysSetEnv above where "table full"/"too long" are
genuine failures. currentThreadUnsetEnv's own bool return (which
DOES distinguish "removed" from "was not there", for a kernel-
side caller like shell.c that might want to) is deliberately
discarded at this syscall boundary. */
char name[envEntryMax];
if (!copyUserPath(regs->rdi, name, sizeof(name))) {
regs->rax = (uint64)-1;
return (uint64)regs;
}
currentThreadUnsetEnv(name);
regs->rax = 0;
return (uint64)regs;
}
case sysUnlink: {
char path[256];
if (!copyUserPath(regs->rdi, path, sizeof(path)))