isolate POSIX builds from the host UCRT, wire lwext4 and ntfs-3g as ext4.sys and ntfs.sys, split the FAT driver into directory/file/async/driver/mount units, add posixsrv and dwm plus input/console/desktop syscall clients and a pile of new smoke targets, rename serial.sys to cereal.sys, name HDA/USB/lwIP/AHCI workers, harden ATA probing/reset/removal around actual hardware deadlines, absent-channel detection, diagnostics and explicit worker lifetime, redo ACPI S5 shutdown around GAS/MMIO and HW-reduced firmware, scan SSDTs for _S5 and deal with Intel SMI sleep trapping, make serial and SMP timeouts use real monotonic deadlines, add thread names and fix terminal thread teardown, scheduler and APC prepare/commit races, make advisory file locks queryable and preserve split ranges and add mutable file append state, add shared-memory pipes with kernel-assisted wait/wake, introduce capability-scoped input and display managers, split surface map rights into read/write, add explicit unmap and replace present with commit/generation/damage tracking while keeping physical presentation under the display manager, decouple native exception classes from Win32 exception numbers and translate them in kernel32, add opaque process startup data, bump the resource protocol to v3 with namespace directories, symlinks and enumeration and service control to v2 with generic READY handle exports, add the new POSIX errno/status surface and rebuild fds around posixsrv-owned shared open descriptions, descriptor-local flags, exact inheritance snapshots, dup/fcntl/record locks and shared-ring pipes, add waitpid, POSIX credentials/groups/sessions/passwd/group lookups and move sockets onto stable open descriptions, port the shells and apps to the new console/input services and surface commit API, teach init to load services.ini and start/supervise RSSRV, DWM and generic services under restricted capabilities while publishing their endpoints through RSSRV, split RSSRV into namespace, volume, display, session, input, console and resource components and make /SystemRoot a real symlink to the independently published system volume, shift the syscall table again, expand lock/resource/surface/POSIX/service/thread smoke coverage, make docs scream ASK QUESTIONS and DISCUSS at LLMs, replace MIT No Attribution with WTFPL+.

This commit is contained in:
maksw committed 2026-09-16 10:33:20 +02:00
1 parent 3dacbd32c8
commit 73abd6f90d
441 files changed
+187073 -6549

No files matched your search

+458 -131
View File
@@ -1,53 +1,223 @@
// POSIX compatibility support for posix io.
// POSIX compatibility support for byte-stream file I/O.
#include <stddef.h>
#include <string.h>
#include <intrin.h>
#include <ntlite/syscall.h>
#include <ntlite/console_service.h>
#include <ntlite/path.h>
#include "posix.h"
#include "posix_internal.h"
#include "posix_fd.h"
#include "posix_path.h"
// Implements the clearscreen operation.
__declspec(dllexport) void clearscreen(void) {
SysClearScreen(0x012456);
// Returns whether one open description permits reading.
static bool PosixDescriptionReadable(const POSIX_OPEN_DESCRIPTION* description) {
return description && (PosixFdGetStatusFlags(description) & O_ACCMODE) != O_WRONLY;
}
// Implements the clearkeyboard operation.
__declspec(dllexport) void clearkeyboard(void) {
INPUT_KEY key;
while (SysPollKeyboard(&key) == NTLSTATUS_SUCCESS) {
char ignored;
(void)SysReadKeyboardChar(&ignored);
// Returns whether one open description permits writing.
static bool PosixDescriptionWritable(const POSIX_OPEN_DESCRIPTION* description) {
return description && (PosixFdGetStatusFlags(description) & O_ACCMODE) != O_RDONLY;
}
// Returns the server-owned shared ring behind one pipe open description.
static SYS_PIPE_SHARED_STATE* PosixPipeShared(POSIX_OPEN_DESCRIPTION* description) {
if (!description || !description->Shared || description->Shared->SharedObjectData == 0) {
errno = EIO;
return (SYS_PIPE_SHARED_STATE*)0;
}
SYS_PIPE_SHARED_STATE* shared =
(SYS_PIPE_SHARED_STATE*)(uintptr_t)description->Shared->SharedObjectData;
if (shared->Magic != SYS_PIPE_SHARED_MAGIC || shared->Version != SYS_PIPE_SHARED_VERSION ||
shared->Capacity != SYS_PIPE_BUFFER_CAPACITY ||
shared->HeaderBytes != SYS_PIPE_SHARED_HEADER_BYTES) {
errno = EIO;
return (SYS_PIPE_SHARED_STATE*)0;
}
return shared;
}
// Acquires one shared pipe-side serialization lock without entering the kernel.
static void PosixPipeLock(volatile long* lock) {
while (_InterlockedCompareExchange(lock, 1, 0) != 0)
_mm_pause();
_ReadWriteBarrier();
}
// Releases one shared pipe-side serialization lock.
static void PosixPipeUnlock(volatile long* lock) {
_ReadWriteBarrier();
_InterlockedExchange(lock, 0);
}
// Returns buffered bytes, rejecting corrupted shared counters.
static int PosixPipeUsed(SYS_PIPE_SHARED_STATE* shared, uint64_t* usedOut) {
uint64_t readPosition = shared->ReadPosition;
_ReadWriteBarrier();
uint64_t writePosition = shared->WritePosition;
uint64_t used = writePosition - readPosition;
if (used > SYS_PIPE_BUFFER_CAPACITY) {
errno = EIO;
return -1;
}
*usedOut = used;
return 0;
}
// Copies bytes out of the shared circular pipe buffer.
static void PosixPipeCopyOut(SYS_PIPE_SHARED_STATE* shared, uint64_t readPosition,
void* buffer, size_t length) {
size_t offset = (size_t)(readPosition % SYS_PIPE_BUFFER_CAPACITY);
size_t first = SYS_PIPE_BUFFER_CAPACITY - offset;
if (first > length) first = length;
memcpy(buffer, shared->Buffer + offset, first);
if (first < length)
memcpy((uint8_t*)buffer + first, shared->Buffer, length - first);
}
// Copies bytes into the shared circular pipe buffer.
static void PosixPipeCopyIn(SYS_PIPE_SHARED_STATE* shared, uint64_t writePosition,
const void* buffer, size_t length) {
size_t offset = (size_t)(writePosition % SYS_PIPE_BUFFER_CAPACITY);
size_t first = SYS_PIPE_BUFFER_CAPACITY - offset;
if (first > length) first = length;
memcpy(shared->Buffer + offset, buffer, first);
if (first < length)
memcpy(shared->Buffer, (const uint8_t*)buffer + first, length - first);
}
// Reads one pipe entirely through the shared user mapping except when blocking.
static ssize_t PosixPipeRead(POSIX_OPEN_DESCRIPTION* description, void* buffer, size_t length) {
SYS_PIPE_SHARED_STATE* shared = PosixPipeShared(description);
if (!shared) return -1;
for (;;) {
PosixPipeLock(&shared->ReadLock);
uint64_t used = 0;
if (PosixPipeUsed(shared, &used) != 0) {
PosixPipeUnlock(&shared->ReadLock);
return -1;
}
if (used != 0) {
size_t transfer = length < used ? length : (size_t)used;
uint64_t readPosition = shared->ReadPosition;
PosixPipeCopyOut(shared, readPosition, buffer, transfer);
_ReadWriteBarrier();
shared->ReadPosition = readPosition + transfer;
_ReadWriteBarrier();
long writeWaiters = shared->WriteWaiters;
PosixPipeUnlock(&shared->ReadLock);
if (writeWaiters != 0)
(void)SysNotifyPipe(description->KHandle);
return (ssize_t)transfer;
}
if (shared->WriterOpen == 0) {
PosixPipeUnlock(&shared->ReadLock);
return 0;
}
if (PosixFdGetStatusFlags(description) & O_NONBLOCK) {
PosixPipeUnlock(&shared->ReadLock);
errno = EAGAIN;
return -1;
}
PosixPipeUnlock(&shared->ReadLock);
uint32_t status = SysWait(description->KHandle, SYS_WAIT_FLAG_NONE);
if (status != NTLSTATUS_SUCCESS) {
errno = PosixStatusToErrno(status);
return -1;
}
}
}
// Opens the requested operation.
// Writes one pipe entirely through the shared user mapping except when blocking/waking.
static ssize_t PosixPipeWrite(POSIX_OPEN_DESCRIPTION* description, const void* buffer, size_t length) {
SYS_PIPE_SHARED_STATE* shared = PosixPipeShared(description);
if (!shared) return -1;
for (;;) {
PosixPipeLock(&shared->WriteLock);
if (shared->ReaderOpen == 0) {
PosixPipeUnlock(&shared->WriteLock);
errno = EPIPE;
return -1;
}
uint64_t used = 0;
if (PosixPipeUsed(shared, &used) != 0) {
PosixPipeUnlock(&shared->WriteLock);
return -1;
}
size_t available = SYS_PIPE_BUFFER_CAPACITY - (size_t)used;
size_t transfer = 0;
if (length <= SYS_PIPE_ATOMIC_WRITE_MAX) {
if (available >= length)
transfer = length;
} else if (available != 0) {
transfer = length < available ? length : available;
}
if (transfer != 0) {
uint64_t writePosition = shared->WritePosition;
PosixPipeCopyIn(shared, writePosition, buffer, transfer);
_ReadWriteBarrier();
shared->WritePosition = writePosition + transfer;
_ReadWriteBarrier();
long readWaiters = shared->ReadWaiters;
PosixPipeUnlock(&shared->WriteLock);
if (readWaiters != 0)
(void)SysNotifyPipe(description->KHandle);
return (ssize_t)transfer;
}
if (PosixFdGetStatusFlags(description) & O_NONBLOCK) {
PosixPipeUnlock(&shared->WriteLock);
errno = EAGAIN;
return -1;
}
PosixPipeUnlock(&shared->WriteLock);
uint32_t status = SysWait(description->KHandle, SYS_WAIT_FLAG_NONE);
if (status != NTLSTATUS_SUCCESS) {
errno = PosixStatusToErrno(status);
return -1;
}
}
}
// Clears the native console display.
__declspec(dllexport) void clearscreen(void) {
(void)NtlConsoleClear(SYS_HANDLE_INVALID, 0x012456);
}
// Flushes pending native console keyboard input.
__declspec(dllexport) void clearkeyboard(void) {
(void)NtlConsoleFlushInput(SYS_HANDLE_INVALID);
}
// Opens one native file or synthetic POSIX device and returns a process-local descriptor.
__declspec(dllexport) int open(const char* path, int flags, ...) {
if (!path || (flags & O_ACCMODE) == O_ACCMODE) {
errno = EINVAL;
return -1;
}
char native[512];
const char* p = PosixTranslatePath(path, native, sizeof(native));
uint32_t pid = SysGetCurrentPid();
FD_TYPE type = FD_FILE;
int statusFlags = flags & (O_ACCMODE | O_APPEND | O_NONBLOCK);
if (strcmp(p, SYNTH_DEVNULL) == 0)
return PosixFdCreate(PosixFdDevNull, SYS_HANDLE_INVALID, statusFlags);
if (strcmp(p, SYNTH_DEVZERO) == 0)
return PosixFdCreate(PosixFdDevZero, SYS_HANDLE_INVALID, statusFlags);
// 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 access = SYS_FILE_ACCESS_QUERY;
uint32_t kh = SYS_HANDLE_INVALID;
uint32_t access = SYS_FILE_ACCESS_QUERY | SYS_FILE_ACCESS_LOCK;
uint32_t disposition = SYS_FILE_OPEN_EXISTING;
if ((flags & O_RDWR) == O_RDWR)
if ((flags & O_ACCMODE) == O_RDWR)
access |= SYS_FILE_ACCESS_READ | SYS_FILE_ACCESS_WRITE;
else if (flags & O_WRONLY)
else if ((flags & O_ACCMODE) == O_WRONLY)
access |= SYS_FILE_ACCESS_WRITE;
else
access |= SYS_FILE_ACCESS_READ;
@@ -62,166 +232,323 @@ __declspec(dllexport) int open(const char* path, int flags, ...) {
else if (flags & O_TRUNC)
disposition = SYS_FILE_TRUNCATE_EXISTING;
uint32_t s = NtlOpenFile(SysSvFromCstr(p), access, disposition,
SYS_FILE_FLAG_NONE, &kh);
if (s != 0) { errno = PosixStatusToErrno(s); return -1; }
int fd = FdAlloc(pid, type, kh);
if (fd < 0) {
SysCloseHandle(kh); // FdAlloc already set errno
uint32_t status = NtlOpenFile(SysSvFromCstr(p), access, disposition,
SYS_FILE_FLAG_NONE, &kh);
if (status != NTLSTATUS_SUCCESS) {
errno = PosixStatusToErrno(status);
return -1;
}
int fd = PosixFdCreate(PosixFdFile, kh, statusFlags);
if (fd < 0)
SysCloseHandle(kh);
return fd;
}
// Returns the requested value.
// Reads bytes from one descriptor through its stable open-description reference.
__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;
if (count == 0)
return 0;
if (!buf) {
errno = EINVAL;
return -1;
}
switch (e->Type) {
case FD_CONSOLE_R: {
// Read up to count chars from keyboard, blocking per char.
POSIX_OPEN_DESCRIPTION* description = PosixFdAcquire(fd);
if (!description)
return -1;
if (!PosixDescriptionReadable(description)) {
PosixFdRelease(description);
errno = EBADF;
return -1;
}
ssize_t result = -1;
switch (description->Type) {
case PosixFdConsoleRead: {
char* dst = (char*)buf;
result = (ssize_t)count;
for (size_t i = 0; i < count; i++) {
uint32_t s = SysReadKeyboardChar(&dst[i]);
if (s != NTLSTATUS_SUCCESS) { errno = PosixStatusToErrno(s); return -1; }
if (dst[i] == '\n' || dst[i] == '\r') return (ssize_t)(i + 1);
uint32_t status = NtlConsoleReadCharacter(SYS_HANDLE_INVALID, &dst[i]);
if (status != NTLSTATUS_SUCCESS) {
errno = PosixStatusToErrno(status);
result = -1;
break;
}
if (dst[i] == '\n' || dst[i] == '\r') {
result = (ssize_t)(i + 1u);
break;
}
}
return (ssize_t)count;
break;
}
case FD_DEVNULL:
return 0;
case FD_DEVZERO:
case PosixFdDevNull:
result = 0;
break;
case PosixFdDevZero:
memset(buf, 0, count);
return (ssize_t)count;
case FD_FILE: {
result = (ssize_t)count;
break;
case PosixFdFile: {
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;
SYS_FILE_IO_REQUEST request =
SysMakeFileIoRequest(description->KHandle, buf, count, &got);
uint32_t status = SysReadFile(&request);
if (status != NTLSTATUS_SUCCESS && got == 0)
errno = PosixStatusToErrno(status);
else
result = (ssize_t)got;
break;
}
case FD_SOCKET: {
case PosixFdPipeRead:
result = PosixPipeRead(description, buf, count);
break;
case PosixFdSocket: {
size_t got = 0;
SYS_SOCKET_RECV_REQUEST request = {
sizeof(SYS_SOCKET_RECV_REQUEST), e->KHandle, 0,
sizeof(SYS_SOCKET_RECV_REQUEST), description->KHandle, 0,
buf, count, &got
};
uint32_t s = SysRecvSocket(&request);
if (s != 0) { errno = PosixStatusToErrno(s); return -1; }
return (ssize_t)got;
uint32_t status = SysRecvSocket(&request);
if (status != NTLSTATUS_SUCCESS)
errno = PosixStatusToErrno(status);
else
result = (ssize_t)got;
break;
}
default:
errno = EBADF;
return -1;
break;
}
PosixFdRelease(description);
return result;
}
// Updates the requested value.
// Writes bytes through one descriptor's shared open description.
__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;
if (count == 0)
return 0;
if (!buf) {
errno = EINVAL;
return -1;
}
switch (e->Type) {
case FD_CONSOLE_W: {
SYS_WRITE_CONSOLE_REQUEST req = { sizeof(SYS_WRITE_CONSOLE_REQUEST), SysSvFromParts((const char*)buf, count) };
SysWriteConsole(&req);
return (ssize_t)count;
}
case FD_DEVNULL:
case FD_DEVZERO:
return (ssize_t)count;
case FD_FILE: {
POSIX_OPEN_DESCRIPTION* description = PosixFdAcquire(fd);
if (!description)
return -1;
if (!PosixDescriptionWritable(description)) {
PosixFdRelease(description);
errno = EBADF;
return -1;
}
ssize_t result = -1;
switch (description->Type) {
case PosixFdConsoleWrite: {
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;
uint32_t status = NtlConsoleWrite(SYS_HANDLE_INVALID, buf, count, &written);
if (status != NTLSTATUS_SUCCESS && written == 0)
errno = PosixStatusToErrno(status);
else
result = (ssize_t)written;
break;
}
case FD_SOCKET: {
case PosixFdDevNull:
case PosixFdDevZero:
result = (ssize_t)count;
break;
case PosixFdFile: {
size_t written = 0;
SYS_FILE_IO_REQUEST request =
SysMakeFileIoRequest(description->KHandle, (void*)buf, count, &written);
uint32_t status = SysWriteFile(&request);
if (status != NTLSTATUS_SUCCESS && written == 0)
errno = PosixStatusToErrno(status);
else
result = (ssize_t)written;
break;
}
case PosixFdPipeWrite:
result = PosixPipeWrite(description, buf, count);
break;
case PosixFdSocket: {
size_t sent = 0;
SYS_SOCKET_SEND_REQUEST request = {
sizeof(SYS_SOCKET_SEND_REQUEST), e->KHandle, 0,
sizeof(SYS_SOCKET_SEND_REQUEST), description->KHandle, 0,
buf, count, &sent
};
uint32_t s = SysSendSocket(&request);
if (s != 0) { errno = PosixStatusToErrno(s); return -1; }
return (ssize_t)sent;
uint32_t status = SysSendSocket(&request);
if (status != NTLSTATUS_SUCCESS)
errno = PosixStatusToErrno(status);
else
result = (ssize_t)sent;
break;
}
default:
errno = EBADF;
return -1;
break;
}
PosixFdRelease(description);
return result;
}
// Releases the requested object.
// Closes one descriptor without invalidating concurrent open-description users.
__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 PosixFdClose(fd);
}
// Creates one anonymous pipe whose backing and master endpoint capabilities are owned by posixsrv.
__declspec(dllexport) int pipe(int pipefd[2]) {
if (!pipefd) {
errno = EINVAL;
return -1;
}
NTL_POSIX_REQUEST request;
memset(&request, 0, sizeof(request));
request.Size = sizeof(request);
request.Version = NTL_POSIX_PROTOCOL_VERSION;
request.Operation = NTL_POSIX_OP_CREATE_PIPE;
request.Flags = NTL_POSIX_REQUEST_FLAG_NONE;
SYS_HANDLE handles[2] = { SYS_HANDLE_INVALID, SYS_HANDLE_INVALID };
NTL_POSIX_REPLY reply;
KSTATUS status = PosixRuntimeCallServerExchange(
&request, (const SYS_PORT_HANDLE_TRANSFER*)0, 0, handles, 2u, 2u, &reply);
if (!KSUCCESS(status) || !KSUCCESS(reply.Status)) {
for (uint32_t i = 0; i < 2u; ++i) {
if (handles[i] != SYS_HANDLE_INVALID)
(void)SysCloseHandle(handles[i]);
}
errno = PosixStatusToErrno(KSUCCESS(status) ? reply.Status : status);
return -1;
}
NTL_POSIX_SHARED_OPEN_DESCRIPTION* readShared =
(NTL_POSIX_SHARED_OPEN_DESCRIPTION*)(uintptr_t)reply.SharedOpenDescription;
NTL_POSIX_SHARED_OPEN_DESCRIPTION* writeShared =
(NTL_POSIX_SHARED_OPEN_DESCRIPTION*)(uintptr_t)reply.SharedOpenDescription2;
SYS_PIPE_SHARED_STATE* pipeShared = readShared ?
(SYS_PIPE_SHARED_STATE*)(uintptr_t)readShared->SharedObjectData :
(SYS_PIPE_SHARED_STATE*)0;
int valid = handles[0] != SYS_HANDLE_INVALID && handles[1] != SYS_HANDLE_INVALID &&
reply.OpenDescriptionId != 0 && reply.OpenDescriptionId2 != 0 &&
reply.OpenDescriptionId != reply.OpenDescriptionId2 &&
reply.OpenDescriptionType == NTL_POSIX_OPEN_TYPE_PIPE_READ &&
reply.OpenDescriptionType2 == NTL_POSIX_OPEN_TYPE_PIPE_WRITE &&
reply.OpenStatusFlags == NTL_POSIX_OPEN_STATUS_RDONLY &&
reply.OpenStatusFlags2 == NTL_POSIX_OPEN_STATUS_WRONLY &&
readShared && writeShared &&
readShared->Magic == NTL_POSIX_SHARED_OPEN_MAGIC &&
writeShared->Magic == NTL_POSIX_SHARED_OPEN_MAGIC &&
readShared->Version == NTL_POSIX_SHARED_OPEN_VERSION &&
writeShared->Version == NTL_POSIX_SHARED_OPEN_VERSION &&
readShared->Type == NTL_POSIX_OPEN_TYPE_PIPE_READ &&
writeShared->Type == NTL_POSIX_OPEN_TYPE_PIPE_WRITE &&
readShared->DescriptionId == reply.OpenDescriptionId &&
writeShared->DescriptionId == reply.OpenDescriptionId2 &&
readShared->Reserved == 0 && writeShared->Reserved == 0 &&
readShared->Reserved2 == 0 && writeShared->Reserved2 == 0 &&
readShared->SharedObjectData != 0 &&
readShared->SharedObjectData == writeShared->SharedObjectData &&
pipeShared && pipeShared->Magic == SYS_PIPE_SHARED_MAGIC &&
pipeShared->Version == SYS_PIPE_SHARED_VERSION &&
pipeShared->Capacity == SYS_PIPE_BUFFER_CAPACITY &&
pipeShared->HeaderBytes == SYS_PIPE_SHARED_HEADER_BYTES;
if (!valid) {
(void)SysCloseHandle(handles[0]);
(void)SysCloseHandle(handles[1]);
PosixFdReleaseServerDescription(reply.OpenDescriptionId);
PosixFdReleaseServerDescription(reply.OpenDescriptionId2);
errno = EIO;
return -1;
}
int readFd = PosixFdImport(PosixFdPipeRead, handles[0], reply.OpenDescriptionId,
readShared, 0);
handles[0] = SYS_HANDLE_INVALID;
if (readFd < 0) {
(void)SysCloseHandle(handles[1]);
PosixFdReleaseServerDescription(reply.OpenDescriptionId2);
return -1;
}
int writeFd = PosixFdImport(PosixFdPipeWrite, handles[1], reply.OpenDescriptionId2,
writeShared, 0);
handles[1] = SYS_HANDLE_INVALID;
if (writeFd < 0) {
(void)PosixFdClose(readFd);
return -1;
}
pipefd[0] = readFd;
pipefd[1] = writeFd;
return 0;
}
// Implements the unlink operation.
// Deletes one translated native path.
__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;
}
uint32_t s = NtlDeleteFile(SysSvFromCstr(p));
if (s != 0) { errno = PosixStatusToErrno(s); return -1; }
uint32_t status = NtlDeleteFile(SysSvFromCstr(p));
if (status != NTLSTATUS_SUCCESS) {
errno = PosixStatusToErrno(status);
return -1;
}
return 0;
}
// Implements the lseek operation.
// Repositions the shared file offset owned by an open description.
__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 = 0;
uint32_t s = SysGetFilePos(e->KHandle, &cur);
if (s != 0) { errno = PosixStatusToErrno(s); return -1; }
if (cur > 0x7FFFFFFFULL) { errno = EINVAL; return -1; }
target = (int64_t)cur + (int64_t)offset;
break;
}
case SEEK_END: {
uint64_t size = 0;
uint32_t s = SysGetFileSize(e->KHandle, &size);
if (s != 0) { errno = PosixStatusToErrno(s); return -1; }
if (size > 0x7FFFFFFFULL) { errno = EINVAL; return -1; }
target = (int64_t)size + (int64_t)offset;
break;
}
default:
errno = EINVAL;
return -1;
POSIX_OPEN_DESCRIPTION* description = PosixFdAcquire(fd);
if (!description)
return -1;
if (description->Type != PosixFdFile) {
PosixFdRelease(description);
errno = ESPIPE;
return -1;
}
if (target < 0 || target > 0x7FFFFFFFLL) { errno = EINVAL; return -1; }
int64_t target = 0;
uint32_t status = NTLSTATUS_SUCCESS;
if (whence == SEEK_SET) {
target = (int64_t)offset;
} else if (whence == SEEK_CUR) {
uint64_t current = 0;
status = SysGetFilePos(description->KHandle, &current);
if (status == NTLSTATUS_SUCCESS && current <= 0x7FFFFFFFULL)
target = (int64_t)current + (int64_t)offset;
else if (status == NTLSTATUS_SUCCESS)
status = NTLSTATUS_INVALID_PARAMETER;
} else if (whence == SEEK_END) {
uint64_t size = 0;
status = SysGetFileSize(description->KHandle, &size);
if (status == NTLSTATUS_SUCCESS && size <= 0x7FFFFFFFULL)
target = (int64_t)size + (int64_t)offset;
else if (status == NTLSTATUS_SUCCESS)
status = NTLSTATUS_INVALID_PARAMETER;
} else {
status = NTLSTATUS_INVALID_PARAMETER;
}
uint32_t s = SysSeekFile(e->KHandle, (uint64_t)target);
if (s != 0) { errno = PosixStatusToErrno(s); return -1; }
if (status == NTLSTATUS_SUCCESS && (target < 0 || target > 0x7FFFFFFFLL))
status = NTLSTATUS_INVALID_PARAMETER;
if (status == NTLSTATUS_SUCCESS)
status = SysSeekFile(description->KHandle, (uint64_t)target);
PosixFdRelease(description);
if (status != NTLSTATUS_SUCCESS) {
errno = PosixStatusToErrno(status);
return -1;
}
return (off_t)target;
}