// posix_io.c - open, read, write, close, lseek #include #include #include #include "posix.h" #include "posix_fd.h" #include "posix_path.h" __declspec(dllexport) void clearscreen(void) { SysScreenClear(0x012456); } __declspec(dllexport) void clearkeyboard(void) { while (SysKbPoll()) (void)SysKbReadChar(); } __declspec(dllexport) int open(const char* path, int flags, ...) { char native[512]; const char* p = PosixTranslatePath(path, native, sizeof(native)); uint32_t pid = SysGetCurrentPid(); FD_TYPE type = FD_FILE; // Synthetic devices if (strcmp(p, SYNTH_DEVNULL) == 0) { int fd = FdAlloc(pid, FD_DEVNULL, 0); return fd; } if (strcmp(p, SYNTH_DEVZERO) == 0) { int fd = FdAlloc(pid, FD_DEVZERO, 0); return fd; } uint32_t kh = 0; SYS_PATH_HANDLE_REQUEST req = { SysSvFromCstr(p), &kh }; uint32_t s; if (flags & O_WRONLY) { s = SysCreateFile(&req); } else { s = SysOpenFile(&req); } if (s != 0) { errno = PosixStatusToErrno(s); return -1; } if ((flags & O_TRUNC) && (flags & O_WRONLY)) SysTruncateFile(kh, 0); int fd = FdAlloc(pid, type, kh); if (fd < 0) { SysCloseHandle(kh); // FdAlloc already set errno return -1; } return fd; } __declspec(dllexport) ssize_t read(int fd, void* buf, size_t count) { if (count == 0) return 0; uint32_t pid = SysGetCurrentPid(); FD_ENTRY* e = FdGet(pid, fd); if (!e) return -1; switch (e->Type) { case FD_CONSOLE_R: { // Read up to count chars from keyboard, blocking per char. char* dst = (char*)buf; for (size_t i = 0; i < count; i++) { dst[i] = SysKbReadChar(); if (dst[i] == '\n' || dst[i] == '\r') return (ssize_t)(i + 1); } return (ssize_t)count; } case FD_DEVNULL: return 0; case FD_DEVZERO: memset(buf, 0, count); return (ssize_t)count; case FD_FILE: { size_t got = 0; uint32_t s = SysReadFile(e->KHandle, buf, count, &got); if (s != 0 && got == 0) { errno = PosixStatusToErrno(s); return -1; } return (ssize_t)got; } case FD_SOCKET: { size_t got = 0; uint32_t s = SysRecv(e->KHandle, buf, count, 0, &got); if (s != 0) { errno = PosixStatusToErrno(s); return -1; } return (ssize_t)got; } default: errno = EBADF; return -1; } } __declspec(dllexport) ssize_t write(int fd, const void* buf, size_t count) { if (count == 0) return 0; uint32_t pid = SysGetCurrentPid(); FD_ENTRY* e = FdGet(pid, fd); if (!e) return -1; switch (e->Type) { case FD_CONSOLE_W: { SYS_WRITE_CONSOLE_REQUEST req = { SysSvFromParts((const char*)buf, count) }; SysWriteConsole(&req); return (ssize_t)count; } case FD_DEVNULL: case FD_DEVZERO: return (ssize_t)count; case FD_FILE: { size_t written = 0; uint32_t s = SysWriteFile(e->KHandle, buf, count, &written); if (s != 0 && written == 0) { errno = PosixStatusToErrno(s); return -1; } return (ssize_t)written; } case FD_SOCKET: { size_t sent = 0; uint32_t s = SysSend(e->KHandle, buf, count, 0, &sent); if (s != 0) { errno = PosixStatusToErrno(s); return -1; } return (ssize_t)sent; } default: errno = EBADF; return -1; } } __declspec(dllexport) int close(int fd) { uint32_t pid = SysGetCurrentPid(); FD_ENTRY* e = FdGet(pid, fd); if (!e) return -1; if (e->Type == FD_FILE || e->Type == FD_SOCKET) SysCloseHandle(e->KHandle); FdFree(pid, fd); return 0; } __declspec(dllexport) int unlink(const char* path) { if (!path) { errno = EINVAL; return -1; } char native[512]; const char* p = PosixTranslatePath(path, native, sizeof(native)); if (strcmp(p, SYNTH_DEVNULL) == 0 || strcmp(p, SYNTH_DEVZERO) == 0) { errno = EINVAL; return -1; } SYS_PATH_REQUEST req = { SysSvFromCstr(p) }; uint32_t s = SysDeleteFile(&req); if (s != 0) { errno = PosixStatusToErrno(s); return -1; } return 0; } __declspec(dllexport) off_t lseek(int fd, off_t offset, int whence) { uint32_t pid = SysGetCurrentPid(); FD_ENTRY* e = FdGet(pid, fd); if (!e || e->Type != FD_FILE) { errno = (e ? ESPIPE : EBADF); return -1; } int64_t target = 0; switch (whence) { case SEEK_SET: target = (int64_t)offset; break; case SEEK_CUR: { uint64_t cur = SysGetFilePos(e->KHandle); if (cur > 0x7FFFFFFFULL) { errno = EINVAL; return -1; } target = (int64_t)cur + (int64_t)offset; break; } case SEEK_END: { uint64_t size = SysGetFileSize(e->KHandle); if (size > 0x7FFFFFFFULL) { errno = EINVAL; return -1; } target = (int64_t)size + (int64_t)offset; break; } default: errno = EINVAL; return -1; } if (target < 0 || target > 0x7FFFFFFFLL) { errno = EINVAL; return -1; } uint32_t s = SysSeekFile(e->KHandle, (uint64_t)target); if (s != 0) { errno = PosixStatusToErrno(s); return -1; } return (off_t)target; }