// POSIX compatibility support for posix io. #include #include #include #include "posix.h" #include "posix_fd.h" #include "posix_path.h" // Implements the clearscreen operation. __declspec(dllexport) void clearscreen(void) { SysClearScreen(0x012456); } // Implements the clearkeyboard operation. __declspec(dllexport) void clearkeyboard(void) { while (SysPollKeyboard()) (void)SysReadKeyboardChar(); } // Opens the requested operation. __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; } // Returns the requested value. __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] = SysReadKeyboardChar(); 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; SYS_FILE_IO_REQUEST req = SysMakeFileIoRequest(e->KHandle, buf, count, &got); uint32_t s = SysReadFile(&req); if (s != 0 && got == 0) { errno = PosixStatusToErrno(s); return -1; } return (ssize_t)got; } case FD_SOCKET: { size_t got = 0; uint32_t s = SysRecvSocket(e->KHandle, buf, count, 0, &got); if (s != 0) { errno = PosixStatusToErrno(s); return -1; } return (ssize_t)got; } default: errno = EBADF; return -1; } } // Updates the requested value. __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; SYS_FILE_IO_REQUEST req = SysMakeFileIoRequest(e->KHandle, buf, count, &written); uint32_t s = SysWriteFile(&req); if (s != 0 && written == 0) { errno = PosixStatusToErrno(s); return -1; } return (ssize_t)written; } case FD_SOCKET: { size_t sent = 0; uint32_t s = SysSendSocket(e->KHandle, buf, count, 0, &sent); if (s != 0) { errno = PosixStatusToErrno(s); return -1; } return (ssize_t)sent; } default: errno = EBADF; return -1; } } // Releases the requested object. __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; } // Implements the unlink operation. __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; } // Implements the lseek operation. __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; }