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;
|
regs->rax = (uint64)result;
|
||||||
return (uint64)regs;
|
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;
|
return (uint64)regs;
|
||||||
|
}
|
||||||
case sysGetpid:
|
case sysGetpid:
|
||||||
regs->rax = currentThreadId();
|
regs->rax = currentThreadId();
|
||||||
return (uint64)regs;
|
return (uint64)regs;
|
||||||
@@ -358,6 +374,68 @@ uint64 syscallDispatch(Registers* regs)
|
|||||||
regs->rax = (uint64)(int64)vfsMkdir(path);
|
regs->rax = (uint64)(int64)vfsMkdir(path);
|
||||||
return (uint64)regs;
|
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: {
|
case sysUnlink: {
|
||||||
char path[256];
|
char path[256];
|
||||||
if (!copyUserPath(regs->rdi, path, sizeof(path)))
|
if (!copyUserPath(regs->rdi, path, sizeof(path)))
|
||||||
|
|||||||
Reference in new issue
Block a user