feat: extend syscall
This commit is contained in:
1 parent
5149adf7ae
commit
643fa45f6a
1 file changed
+80
-2
+80
-2
@@ -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)))
|
||||
|
||||
Reference in new issue
Block a user