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:
1 parent
3dacbd32c8
commit
73abd6f90d
441 files changed
+187073
-6549
No files matched your search
@@ -5,7 +5,7 @@
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <ntlite/syscall.h>
|
||||
#include "posix.h"
|
||||
#include "posix_internal.h"
|
||||
#include "posix_fd.h"
|
||||
|
||||
// Implements the bswap16 operation.
|
||||
@@ -284,61 +284,84 @@ static void SysToSockAddr(const SYS_SOCKET_ADDRESS* in, struct sockaddr* addr, s
|
||||
}
|
||||
}
|
||||
|
||||
// Implements the socket Fd Get operation.
|
||||
static FD_ENTRY* SocketFdGet(int fd) {
|
||||
FD_ENTRY* e = FdGet(SysGetCurrentPid(), fd);
|
||||
if (!e) return (FD_ENTRY*)0;
|
||||
if (e->Type != FD_SOCKET) { errno = ENOTSOCK; return (FD_ENTRY*)0; }
|
||||
return e;
|
||||
// Acquires one socket open-description reference.
|
||||
static POSIX_OPEN_DESCRIPTION* SocketFdAcquire(int fd) {
|
||||
POSIX_OPEN_DESCRIPTION* description = PosixFdAcquire(fd);
|
||||
if (!description)
|
||||
return (POSIX_OPEN_DESCRIPTION*)0;
|
||||
if (description->Type != PosixFdSocket) {
|
||||
PosixFdRelease(description);
|
||||
errno = ENOTSOCK;
|
||||
return (POSIX_OPEN_DESCRIPTION*)0;
|
||||
}
|
||||
return description;
|
||||
}
|
||||
|
||||
// Implements the socket operation.
|
||||
// Creates a socket and installs it as a process-local descriptor.
|
||||
__declspec(dllexport) int socket(int domain, int type, int protocol) {
|
||||
uint32_t kh = 0;
|
||||
uint32_t s = SysCreateSocket((uint32_t)domain, (uint32_t)type, (uint32_t)protocol, &kh);
|
||||
if (s != 0) { errno = PosixStatusToErrno(s); return -1; }
|
||||
|
||||
int fd = FdAlloc(SysGetCurrentPid(), FD_SOCKET, kh);
|
||||
if (fd < 0) {
|
||||
SysCloseHandle(kh);
|
||||
uint32_t kh = SYS_HANDLE_INVALID;
|
||||
uint32_t status = SysCreateSocket((uint32_t)domain, (uint32_t)type, (uint32_t)protocol, &kh);
|
||||
if (status != NTLSTATUS_SUCCESS) {
|
||||
errno = PosixStatusToErrno(status);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int fd = PosixFdCreate(PosixFdSocket, kh, O_RDWR);
|
||||
if (fd < 0)
|
||||
SysCloseHandle(kh);
|
||||
return fd;
|
||||
}
|
||||
|
||||
// Implements the bind operation.
|
||||
// Binds one socket descriptor to a local address.
|
||||
__declspec(dllexport) int bind(int fd, const struct sockaddr* addr, socklen_t addrlen) {
|
||||
FD_ENTRY* e = SocketFdGet(fd);
|
||||
if (!e) return -1;
|
||||
SYS_SOCKET_ADDRESS a;
|
||||
if (SockAddrToSys(addr, addrlen, &a) != 0) return -1;
|
||||
uint32_t s = SysBindSocket(e->KHandle, &a, sizeof(a));
|
||||
if (s != 0) { errno = PosixStatusToErrno(s); return -1; }
|
||||
POSIX_OPEN_DESCRIPTION* description = SocketFdAcquire(fd);
|
||||
if (!description) return -1;
|
||||
SYS_SOCKET_ADDRESS address;
|
||||
if (SockAddrToSys(addr, addrlen, &address) != 0) {
|
||||
PosixFdRelease(description);
|
||||
return -1;
|
||||
}
|
||||
uint32_t status = SysBindSocket(description->KHandle, &address, sizeof(address));
|
||||
PosixFdRelease(description);
|
||||
if (status != NTLSTATUS_SUCCESS) {
|
||||
errno = PosixStatusToErrno(status);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Implements the listen operation.
|
||||
// Places one socket into listening state.
|
||||
__declspec(dllexport) int listen(int fd, int backlog) {
|
||||
FD_ENTRY* e = SocketFdGet(fd);
|
||||
if (!e) return -1;
|
||||
uint32_t s = SysListenSocket(e->KHandle, backlog < 0 ? 0u : (uint32_t)backlog);
|
||||
if (s != 0) { errno = PosixStatusToErrno(s); return -1; }
|
||||
POSIX_OPEN_DESCRIPTION* description = SocketFdAcquire(fd);
|
||||
if (!description) return -1;
|
||||
uint32_t status = SysListenSocket(description->KHandle, backlog < 0 ? 0u : (uint32_t)backlog);
|
||||
PosixFdRelease(description);
|
||||
if (status != NTLSTATUS_SUCCESS) {
|
||||
errno = PosixStatusToErrno(status);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Implements the accept operation.
|
||||
// Accepts one socket and installs the accepted endpoint as a new descriptor.
|
||||
__declspec(dllexport) int accept(int fd, struct sockaddr* addr, socklen_t* addrlen) {
|
||||
FD_ENTRY* e = SocketFdGet(fd);
|
||||
if (!e) return -1;
|
||||
POSIX_OPEN_DESCRIPTION* description = SocketFdAcquire(fd);
|
||||
if (!description) return -1;
|
||||
|
||||
SYS_SOCKET_ADDRESS remote;
|
||||
size_t remoteSize = sizeof(remote);
|
||||
uint32_t kh = 0;
|
||||
uint32_t s = SysAcceptSocket(e->KHandle, addr ? &remote : (SYS_SOCKET_ADDRESS*)0,
|
||||
addr ? &remoteSize : (size_t*)0, &kh);
|
||||
if (s != 0) { errno = PosixStatusToErrno(s); return -1; }
|
||||
uint32_t kh = SYS_HANDLE_INVALID;
|
||||
uint32_t status = SysAcceptSocket(description->KHandle,
|
||||
addr ? &remote : (SYS_SOCKET_ADDRESS*)0,
|
||||
addr ? &remoteSize : (size_t*)0,
|
||||
&kh);
|
||||
PosixFdRelease(description);
|
||||
if (status != NTLSTATUS_SUCCESS) {
|
||||
errno = PosixStatusToErrno(status);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int outfd = FdAlloc(SysGetCurrentPid(), FD_SOCKET, kh);
|
||||
int outfd = PosixFdCreate(PosixFdSocket, kh, O_RDWR);
|
||||
if (outfd < 0) {
|
||||
SysCloseHandle(kh);
|
||||
return -1;
|
||||
@@ -347,113 +370,145 @@ __declspec(dllexport) int accept(int fd, struct sockaddr* addr, socklen_t* addrl
|
||||
return outfd;
|
||||
}
|
||||
|
||||
// Implements the connect operation.
|
||||
// Connects one socket descriptor to a remote address.
|
||||
__declspec(dllexport) int connect(int fd, const struct sockaddr* addr, socklen_t addrlen) {
|
||||
FD_ENTRY* e = SocketFdGet(fd);
|
||||
if (!e) return -1;
|
||||
SYS_SOCKET_ADDRESS a;
|
||||
if (SockAddrToSys(addr, addrlen, &a) != 0) return -1;
|
||||
uint32_t s = SysConnectSocket(e->KHandle, &a, sizeof(a));
|
||||
if (s != 0) { errno = PosixStatusToErrno(s); return -1; }
|
||||
POSIX_OPEN_DESCRIPTION* description = SocketFdAcquire(fd);
|
||||
if (!description) return -1;
|
||||
SYS_SOCKET_ADDRESS address;
|
||||
if (SockAddrToSys(addr, addrlen, &address) != 0) {
|
||||
PosixFdRelease(description);
|
||||
return -1;
|
||||
}
|
||||
uint32_t status = SysConnectSocket(description->KHandle, &address, sizeof(address));
|
||||
PosixFdRelease(description);
|
||||
if (status != NTLSTATUS_SUCCESS) {
|
||||
errno = PosixStatusToErrno(status);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Implements the send operation.
|
||||
// Sends bytes through one socket descriptor.
|
||||
__declspec(dllexport) ssize_t send(int fd, const void* buf, size_t len, int flags) {
|
||||
FD_ENTRY* e = SocketFdGet(fd);
|
||||
if (!e) return -1;
|
||||
POSIX_OPEN_DESCRIPTION* description = SocketFdAcquire(fd);
|
||||
if (!description) return -1;
|
||||
size_t sent = 0;
|
||||
SYS_SOCKET_SEND_REQUEST request = {
|
||||
sizeof(SYS_SOCKET_SEND_REQUEST), e->KHandle, (uint32_t)flags,
|
||||
sizeof(SYS_SOCKET_SEND_REQUEST), description->KHandle, (uint32_t)flags,
|
||||
buf, len, &sent
|
||||
};
|
||||
uint32_t s = SysSendSocket(&request);
|
||||
if (s != 0) { errno = PosixStatusToErrno(s); return -1; }
|
||||
uint32_t status = SysSendSocket(&request);
|
||||
PosixFdRelease(description);
|
||||
if (status != NTLSTATUS_SUCCESS) {
|
||||
errno = PosixStatusToErrno(status);
|
||||
return -1;
|
||||
}
|
||||
return (ssize_t)sent;
|
||||
}
|
||||
|
||||
// Implements the recv operation.
|
||||
// Receives bytes through one socket descriptor.
|
||||
__declspec(dllexport) ssize_t recv(int fd, void* buf, size_t len, int flags) {
|
||||
FD_ENTRY* e = SocketFdGet(fd);
|
||||
if (!e) return -1;
|
||||
POSIX_OPEN_DESCRIPTION* description = SocketFdAcquire(fd);
|
||||
if (!description) return -1;
|
||||
size_t got = 0;
|
||||
SYS_SOCKET_RECV_REQUEST request = {
|
||||
sizeof(SYS_SOCKET_RECV_REQUEST), e->KHandle, (uint32_t)flags,
|
||||
sizeof(SYS_SOCKET_RECV_REQUEST), description->KHandle, (uint32_t)flags,
|
||||
buf, len, &got
|
||||
};
|
||||
uint32_t s = SysRecvSocket(&request);
|
||||
if (s != 0) { errno = PosixStatusToErrno(s); return -1; }
|
||||
uint32_t status = SysRecvSocket(&request);
|
||||
PosixFdRelease(description);
|
||||
if (status != NTLSTATUS_SUCCESS) {
|
||||
errno = PosixStatusToErrno(status);
|
||||
return -1;
|
||||
}
|
||||
return (ssize_t)got;
|
||||
}
|
||||
|
||||
// Sends one datagram to a remote address.
|
||||
__declspec(dllexport) ssize_t sendto(int fd, const void* buf, size_t len, int flags,
|
||||
const struct sockaddr* dest, socklen_t destlen) {
|
||||
FD_ENTRY* e = SocketFdGet(fd);
|
||||
if (!e) return -1;
|
||||
POSIX_OPEN_DESCRIPTION* description = SocketFdAcquire(fd);
|
||||
if (!description) return -1;
|
||||
SYS_SOCKET_ADDRESS remote;
|
||||
if (SockAddrToSys(dest, destlen, &remote) != 0) return -1;
|
||||
if (SockAddrToSys(dest, destlen, &remote) != 0) {
|
||||
PosixFdRelease(description);
|
||||
return -1;
|
||||
}
|
||||
|
||||
size_t sent = 0;
|
||||
SYS_SOCKET_SEND_TO_REQUEST req;
|
||||
memset(&req, 0, sizeof(req));
|
||||
req.Size = sizeof(req);
|
||||
req.Buffer = buf;
|
||||
req.Length = len;
|
||||
req.Flags = (uint32_t)flags;
|
||||
req.RemoteAddress = &remote;
|
||||
req.RemoteAddressSize = sizeof(remote);
|
||||
req.SentOut = &sent;
|
||||
SYS_SOCKET_SEND_TO_REQUEST request;
|
||||
memset(&request, 0, sizeof(request));
|
||||
request.Size = sizeof(request);
|
||||
request.Buffer = buf;
|
||||
request.Length = len;
|
||||
request.Flags = (uint32_t)flags;
|
||||
request.RemoteAddress = &remote;
|
||||
request.RemoteAddressSize = sizeof(remote);
|
||||
request.SentOut = &sent;
|
||||
|
||||
uint32_t s = SysSendToSocket(e->KHandle, &req);
|
||||
if (s != 0) { errno = PosixStatusToErrno(s); return -1; }
|
||||
uint32_t status = SysSendToSocket(description->KHandle, &request);
|
||||
PosixFdRelease(description);
|
||||
if (status != NTLSTATUS_SUCCESS) {
|
||||
errno = PosixStatusToErrno(status);
|
||||
return -1;
|
||||
}
|
||||
return (ssize_t)sent;
|
||||
}
|
||||
|
||||
// Receives one datagram and optionally reports its source address.
|
||||
__declspec(dllexport) ssize_t recvfrom(int fd, void* buf, size_t len, int flags,
|
||||
struct sockaddr* src, socklen_t* srclen) {
|
||||
FD_ENTRY* e = SocketFdGet(fd);
|
||||
if (!e) return -1;
|
||||
POSIX_OPEN_DESCRIPTION* description = SocketFdAcquire(fd);
|
||||
if (!description) return -1;
|
||||
|
||||
SYS_SOCKET_ADDRESS remote;
|
||||
size_t remoteSize = sizeof(remote);
|
||||
size_t got = 0;
|
||||
SYS_SOCKET_RECV_FROM_REQUEST req;
|
||||
memset(&req, 0, sizeof(req));
|
||||
req.Size = sizeof(req);
|
||||
req.Buffer = buf;
|
||||
req.Length = len;
|
||||
req.Flags = (uint32_t)flags;
|
||||
req.RemoteAddressOut = src ? &remote : (SYS_SOCKET_ADDRESS*)0;
|
||||
req.RemoteAddressSizeInOut = src ? &remoteSize : (size_t*)0;
|
||||
req.ReceivedOut = &got;
|
||||
SYS_SOCKET_RECV_FROM_REQUEST request;
|
||||
memset(&request, 0, sizeof(request));
|
||||
request.Size = sizeof(request);
|
||||
request.Buffer = buf;
|
||||
request.Length = len;
|
||||
request.Flags = (uint32_t)flags;
|
||||
request.RemoteAddressOut = src ? &remote : (SYS_SOCKET_ADDRESS*)0;
|
||||
request.RemoteAddressSizeInOut = src ? &remoteSize : (size_t*)0;
|
||||
request.ReceivedOut = &got;
|
||||
|
||||
uint32_t s = SysRecvFromSocket(e->KHandle, &req);
|
||||
if (s != 0) { errno = PosixStatusToErrno(s); return -1; }
|
||||
uint32_t status = SysRecvFromSocket(description->KHandle, &request);
|
||||
PosixFdRelease(description);
|
||||
if (status != NTLSTATUS_SUCCESS) {
|
||||
errno = PosixStatusToErrno(status);
|
||||
return -1;
|
||||
}
|
||||
if (src) SysToSockAddr(&remote, src, srclen);
|
||||
return (ssize_t)got;
|
||||
}
|
||||
|
||||
// Implements the shutdown operation.
|
||||
// Shuts down one or both directions of a socket.
|
||||
__declspec(dllexport) int shutdown(int fd, int how) {
|
||||
FD_ENTRY* e = SocketFdGet(fd);
|
||||
if (!e) return -1;
|
||||
uint32_t s = SysShutdownSocket(e->KHandle, (uint32_t)how);
|
||||
if (s != 0) { errno = PosixStatusToErrno(s); return -1; }
|
||||
POSIX_OPEN_DESCRIPTION* description = SocketFdAcquire(fd);
|
||||
if (!description) return -1;
|
||||
uint32_t status = SysShutdownSocket(description->KHandle, (uint32_t)how);
|
||||
PosixFdRelease(description);
|
||||
if (status != NTLSTATUS_SUCCESS) {
|
||||
errno = PosixStatusToErrno(status);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Implements the timeval To Ms operation.
|
||||
// Converts one timeval into a bounded millisecond count.
|
||||
static uint32_t TimevalToMs(const struct timeval* tv) {
|
||||
if (!tv) return 0;
|
||||
uint64_t ms = (uint64_t)tv->tv_sec * 1000u + (uint64_t)(tv->tv_usec / 1000);
|
||||
return ms > 0xFFFFFFFFu ? 0xFFFFFFFFu : (uint32_t)ms;
|
||||
}
|
||||
|
||||
// Implements the setsockopt operation.
|
||||
// Sets one supported socket option.
|
||||
__declspec(dllexport) int setsockopt(int fd, int level, int optname, const void* optval, socklen_t optlen) {
|
||||
if (level != SOL_SOCKET || !optval) { errno = EINVAL; return -1; }
|
||||
FD_ENTRY* e = SocketFdGet(fd);
|
||||
if (!e) return -1;
|
||||
POSIX_OPEN_DESCRIPTION* description = SocketFdAcquire(fd);
|
||||
if (!description) return -1;
|
||||
|
||||
uint32_t option = 0;
|
||||
uint32_t value = 0;
|
||||
@@ -461,50 +516,80 @@ __declspec(dllexport) int setsockopt(int fd, int level, int optname, const void*
|
||||
option = (optname == SO_RCVTIMEO) ? SYS_SOCKET_OPT_RECV_TIMEOUT_MS : SYS_SOCKET_OPT_SEND_TIMEOUT_MS;
|
||||
if (optlen == sizeof(struct timeval)) value = TimevalToMs((const struct timeval*)optval);
|
||||
else if (optlen == sizeof(uint32_t)) memcpy(&value, optval, sizeof(value));
|
||||
else { errno = EINVAL; return -1; }
|
||||
else {
|
||||
PosixFdRelease(description);
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
} else if (optname == SO_NONBLOCK) {
|
||||
option = SYS_SOCKET_OPT_NONBLOCKING;
|
||||
if (optlen < sizeof(int)) { errno = EINVAL; return -1; }
|
||||
if (optlen < sizeof(int)) {
|
||||
PosixFdRelease(description);
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
value = (*(const int*)optval) ? 1u : 0u;
|
||||
} else {
|
||||
PosixFdRelease(description);
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
SYS_SOCKET_OPTION_REQUEST req;
|
||||
memset(&req, 0, sizeof(req));
|
||||
req.Size = sizeof(req);
|
||||
req.Option = option;
|
||||
req.Value = &value;
|
||||
req.ValueSize = sizeof(value);
|
||||
uint32_t s = SysSetSocketOption(e->KHandle, &req);
|
||||
if (s != 0) { errno = PosixStatusToErrno(s); return -1; }
|
||||
if (optname == SO_NONBLOCK) {
|
||||
int flags = PosixFdGetStatusFlags(description);
|
||||
if (value) flags |= O_NONBLOCK;
|
||||
else flags &= ~O_NONBLOCK;
|
||||
int result = PosixFdSetStatusFlags(description, flags);
|
||||
PosixFdRelease(description);
|
||||
return result;
|
||||
}
|
||||
|
||||
SYS_SOCKET_OPTION_REQUEST request;
|
||||
memset(&request, 0, sizeof(request));
|
||||
request.Size = sizeof(request);
|
||||
request.Option = option;
|
||||
request.Value = &value;
|
||||
request.ValueSize = sizeof(value);
|
||||
uint32_t status = SysSetSocketOption(description->KHandle, &request);
|
||||
PosixFdRelease(description);
|
||||
if (status != NTLSTATUS_SUCCESS) {
|
||||
errno = PosixStatusToErrno(status);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Implements the getsockopt operation.
|
||||
// Queries one supported socket option.
|
||||
__declspec(dllexport) int getsockopt(int fd, int level, int optname, void* optval, socklen_t* optlen) {
|
||||
if (level != SOL_SOCKET || !optval || !optlen) { errno = EINVAL; return -1; }
|
||||
FD_ENTRY* e = SocketFdGet(fd);
|
||||
if (!e) return -1;
|
||||
POSIX_OPEN_DESCRIPTION* description = SocketFdAcquire(fd);
|
||||
if (!description) return -1;
|
||||
|
||||
uint32_t option = 0;
|
||||
if (optname == SO_RCVTIMEO) option = SYS_SOCKET_OPT_RECV_TIMEOUT_MS;
|
||||
else if (optname == SO_SNDTIMEO) option = SYS_SOCKET_OPT_SEND_TIMEOUT_MS;
|
||||
else if (optname == SO_NONBLOCK) option = SYS_SOCKET_OPT_NONBLOCKING;
|
||||
else { errno = ENOSYS; return -1; }
|
||||
else {
|
||||
PosixFdRelease(description);
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint32_t value = 0;
|
||||
size_t actual = sizeof(value);
|
||||
SYS_SOCKET_OPTION_REQUEST req;
|
||||
memset(&req, 0, sizeof(req));
|
||||
req.Size = sizeof(req);
|
||||
req.Option = option;
|
||||
req.Value = &value;
|
||||
req.ValueSize = sizeof(value);
|
||||
req.ActualSizeOut = &actual;
|
||||
uint32_t s = SysGetSocketOption(e->KHandle, &req);
|
||||
if (s != 0) { errno = PosixStatusToErrno(s); return -1; }
|
||||
SYS_SOCKET_OPTION_REQUEST request;
|
||||
memset(&request, 0, sizeof(request));
|
||||
request.Size = sizeof(request);
|
||||
request.Option = option;
|
||||
request.Value = &value;
|
||||
request.ValueSize = sizeof(value);
|
||||
request.ActualSizeOut = &actual;
|
||||
uint32_t status = SysGetSocketOption(description->KHandle, &request);
|
||||
PosixFdRelease(description);
|
||||
if (status != NTLSTATUS_SUCCESS) {
|
||||
errno = PosixStatusToErrno(status);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((optname == SO_RCVTIMEO || optname == SO_SNDTIMEO) && *optlen >= sizeof(struct timeval)) {
|
||||
struct timeval* tv = (struct timeval*)optval;
|
||||
@@ -521,24 +606,35 @@ __declspec(dllexport) int getsockopt(int fd, int level, int optname, void* optva
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Polls the requested operation.
|
||||
// Polls socket and pipe descriptors while holding stable open-description references.
|
||||
__declspec(dllexport) int poll(struct pollfd* fds, nfds_t nfds, int timeout) {
|
||||
if (!fds || nfds == 0 || nfds > 64) { errno = EINVAL; return -1; }
|
||||
if (!fds || nfds == 0 || nfds > POSIX_FD_MAX) { errno = EINVAL; return -1; }
|
||||
|
||||
SYS_POLLFD* kfds = (SYS_POLLFD*)malloc(sizeof(SYS_POLLFD) * nfds);
|
||||
if (!kfds) { errno = ENOMEM; return -1; }
|
||||
SYS_POLLFD* kfds = (SYS_POLLFD*)calloc(nfds, sizeof(SYS_POLLFD));
|
||||
POSIX_OPEN_DESCRIPTION** descriptions =
|
||||
(POSIX_OPEN_DESCRIPTION**)calloc(nfds, sizeof(POSIX_OPEN_DESCRIPTION*));
|
||||
if (!kfds || !descriptions) {
|
||||
free(kfds);
|
||||
free(descriptions);
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (nfds_t i = 0; i < nfds; i++) {
|
||||
kfds[i].Handle = 0;
|
||||
kfds[i].Events = 0;
|
||||
kfds[i].ReturnedEvents = 0;
|
||||
|
||||
fds[i].revents = 0;
|
||||
FD_ENTRY* e = FdGet(SysGetCurrentPid(), fds[i].fd);
|
||||
if (!e || e->Type != FD_SOCKET) {
|
||||
descriptions[i] = PosixFdAcquire(fds[i].fd);
|
||||
if (!descriptions[i] ||
|
||||
(descriptions[i]->Type != PosixFdSocket &&
|
||||
descriptions[i]->Type != PosixFdPipeRead &&
|
||||
descriptions[i]->Type != PosixFdPipeWrite)) {
|
||||
if (descriptions[i]) {
|
||||
PosixFdRelease(descriptions[i]);
|
||||
descriptions[i] = (POSIX_OPEN_DESCRIPTION*)0;
|
||||
}
|
||||
fds[i].revents = POLLNVAL;
|
||||
continue;
|
||||
}
|
||||
kfds[i].Handle = e->KHandle;
|
||||
kfds[i].Handle = descriptions[i]->KHandle;
|
||||
if (fds[i].events & POLLIN) kfds[i].Events |= SYS_POLL_READ;
|
||||
if (fds[i].events & POLLOUT) kfds[i].Events |= SYS_POLL_WRITE;
|
||||
if (fds[i].events & POLLERR) kfds[i].Events |= SYS_POLL_ERROR;
|
||||
@@ -547,33 +643,38 @@ __declspec(dllexport) int poll(struct pollfd* fds, nfds_t nfds, int timeout) {
|
||||
|
||||
size_t ready = 0;
|
||||
uint32_t timeoutMs = timeout < 0 ? SYS_POLL_TIMEOUT_INFINITE : (uint32_t)timeout;
|
||||
SYS_POLL_REQUEST req;
|
||||
memset(&req, 0, sizeof(req));
|
||||
req.Size = sizeof(req);
|
||||
req.TimeoutMs = timeoutMs;
|
||||
req.Fds = kfds;
|
||||
req.Count = nfds;
|
||||
req.ReadyOut = &ready;
|
||||
KSTATUS s = SysPoll(&req);
|
||||
if (s != 0) {
|
||||
free(kfds);
|
||||
errno = PosixStatusToErrno(s);
|
||||
return -1;
|
||||
}
|
||||
SYS_POLL_REQUEST request;
|
||||
memset(&request, 0, sizeof(request));
|
||||
request.Size = sizeof(request);
|
||||
request.TimeoutMs = timeoutMs;
|
||||
request.Fds = kfds;
|
||||
request.Count = nfds;
|
||||
request.ReadyOut = &ready;
|
||||
KSTATUS status = SysPoll(&request);
|
||||
|
||||
int out = 0;
|
||||
for (nfds_t i = 0; i < nfds; i++) {
|
||||
short re = 0;
|
||||
if (kfds[i].ReturnedEvents & SYS_POLL_READ) re |= POLLIN;
|
||||
if (kfds[i].ReturnedEvents & SYS_POLL_WRITE) re |= POLLOUT;
|
||||
if (kfds[i].ReturnedEvents & SYS_POLL_ERROR) re |= POLLERR;
|
||||
if (kfds[i].ReturnedEvents & SYS_POLL_HANGUP) re |= POLLHUP;
|
||||
if (kfds[i].ReturnedEvents & SYS_POLL_INVALID) re |= POLLNVAL;
|
||||
fds[i].revents = re;
|
||||
if (re) out++;
|
||||
if (status == NTLSTATUS_SUCCESS) {
|
||||
for (nfds_t i = 0; i < nfds; i++) {
|
||||
short revents = fds[i].revents;
|
||||
if (kfds[i].ReturnedEvents & SYS_POLL_READ) revents |= POLLIN;
|
||||
if (kfds[i].ReturnedEvents & SYS_POLL_WRITE) revents |= POLLOUT;
|
||||
if (kfds[i].ReturnedEvents & SYS_POLL_ERROR) revents |= POLLERR;
|
||||
if (kfds[i].ReturnedEvents & SYS_POLL_HANGUP) revents |= POLLHUP;
|
||||
if (kfds[i].ReturnedEvents & SYS_POLL_INVALID) revents |= POLLNVAL;
|
||||
fds[i].revents = revents;
|
||||
if (revents) out++;
|
||||
}
|
||||
}
|
||||
|
||||
for (nfds_t i = 0; i < nfds; i++)
|
||||
PosixFdRelease(descriptions[i]);
|
||||
free(descriptions);
|
||||
free(kfds);
|
||||
|
||||
if (status != NTLSTATUS_SUCCESS) {
|
||||
errno = PosixStatusToErrno(status);
|
||||
return -1;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user