159 lines
5.0 KiB
C
159 lines
5.0 KiB
C
// posix_io.c - open, read, write, close, lseek
|
|
#include <stddef.h>
|
|
#include <string.h>
|
|
#include "posix.h"
|
|
#include "posix_fd.h"
|
|
#include "posix_path.h"
|
|
|
|
extern uint32_t SysGetCurrentPid(void);
|
|
extern uint32_t SysOpenFile (const char* path, uint32_t* handleOut);
|
|
extern uint32_t SysCreateFile (const char* path, uint32_t* handleOut);
|
|
extern uint32_t SysTruncateFile(uint32_t handle, uint64_t newSize);
|
|
extern uint32_t SysReadFile (uint32_t handle, void* buf, size_t size, size_t* bytesRead);
|
|
extern uint32_t SysWriteFile (uint32_t handle, const void* buf, size_t size, size_t* written);
|
|
extern uint32_t SysSeekFile (uint32_t handle, uint64_t offset);
|
|
extern uint64_t SysGetFilePos (uint32_t handle);
|
|
extern uint64_t SysGetFileSize(uint32_t handle);
|
|
extern void SysCloseHandle(uint32_t handle);
|
|
extern void SysWriteConsole(const char* buf, size_t len);
|
|
extern char SysKbReadChar(void);
|
|
|
|
// KSTATUS -> errno
|
|
static int KsToErrno(uint32_t s) {
|
|
switch (s) {
|
|
case 0x0000: return 0; // STATUS_SUCCESS
|
|
case 0x0022: return ENOENT; // STATUS_NOT_FOUND
|
|
case 0x0021: return EACCES; // STATUS_ACCESS_DENIED
|
|
case 0x0020: return ENOMEM; // STATUS_NO_MEMORY
|
|
case 0x0023: return EEXIST; // STATUS_ALREADY_EXISTS
|
|
case 0x0010: return EINVAL; // STATUS_INVALID_PARAMETER
|
|
case 0x0012: return ERANGE; // STATUS_BUFFER_TOO_SMALL
|
|
case 0x0002: return ENOSYS; // STATUS_NOT_SUPPORTED
|
|
case 0x0031: return EAGAIN; // STATUS_QUEUE_FULL
|
|
default: return EIO;
|
|
}
|
|
}
|
|
|
|
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;
|
|
uint32_t s;
|
|
if (flags & O_WRONLY) {
|
|
s = SysCreateFile(p, &kh);
|
|
} else {
|
|
s = SysOpenFile(p, &kh);
|
|
}
|
|
if (s != 0) { errno = KsToErrno(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;
|
|
}
|
|
|
|
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 = KsToErrno(s); return -1; }
|
|
return (ssize_t)got;
|
|
}
|
|
default:
|
|
errno = EBADF;
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
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:
|
|
SysWriteConsole((const char*)buf, count);
|
|
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 = KsToErrno(s); return -1; }
|
|
return (ssize_t)written;
|
|
}
|
|
default:
|
|
errno = EBADF;
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
int close(int fd) {
|
|
uint32_t pid = SysGetCurrentPid();
|
|
FD_ENTRY* e = FdGet(pid, fd);
|
|
if (!e) return -1;
|
|
if (e->Type == FD_FILE)
|
|
SysCloseHandle(e->KHandle);
|
|
FdFree(pid, fd);
|
|
return 0;
|
|
}
|
|
|
|
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; }
|
|
|
|
uint64_t target;
|
|
switch (whence) {
|
|
case SEEK_SET: target = (uint64_t)offset; break;
|
|
case SEEK_CUR: target = SysGetFilePos(e->KHandle) + (uint64_t)offset; break;
|
|
case SEEK_END: target = SysGetFileSize(e->KHandle) + (uint64_t)offset; break;
|
|
default: errno = EINVAL; return -1;
|
|
}
|
|
uint32_t s = SysSeekFile(e->KHandle, target);
|
|
if (s != 0) { errno = KsToErrno(s); return -1; }
|
|
return (off_t)target;
|
|
}
|