mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-03-03 07:29:23 +00:00
Support non-blocking i/o across platforms
This change introduces new tests for `O_NONBLOCK` and `SOCK_NONBLOCK` to confirm that non-blocking i/o is now working on all supported platforms, including Windows. For example, you can now say on Windows, MacOS, etc.: socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, IPPROTO_TCP); To create a non-blocking IPv4 TCP socket. Or you can enable non-blocking i/o on an existing socket / pipe / etc. file descriptor by calling fcntl fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK); This functionality is polyfilled on older Linux kernels too, e.g. RHEL5. Now that fcntl() support is much better the FIOCLEX / FIONCLEX polyfills for ioctl() have been removed since they're ugly non-POSIX diameond APIs This change fixes a weakness in kprintf() that was causing Windows trace tools to frequently crash.
This commit is contained in:
parent
5c9e03e3e0
commit
1d4eb08fa1
102 changed files with 678 additions and 331 deletions
|
@ -36,10 +36,13 @@
|
||||||
#include "libc/nt/runtime.h"
|
#include "libc/nt/runtime.h"
|
||||||
#include "libc/nt/struct/byhandlefileinformation.h"
|
#include "libc/nt/struct/byhandlefileinformation.h"
|
||||||
#include "libc/nt/struct/overlapped.h"
|
#include "libc/nt/struct/overlapped.h"
|
||||||
|
#include "libc/nt/winsock.h"
|
||||||
|
#include "libc/sock/internal.h"
|
||||||
#include "libc/stdckdint.h"
|
#include "libc/stdckdint.h"
|
||||||
#include "libc/str/str.h"
|
#include "libc/str/str.h"
|
||||||
#include "libc/sysv/consts/f.h"
|
#include "libc/sysv/consts/f.h"
|
||||||
#include "libc/sysv/consts/fd.h"
|
#include "libc/sysv/consts/fd.h"
|
||||||
|
#include "libc/sysv/consts/fio.h"
|
||||||
#include "libc/sysv/consts/o.h"
|
#include "libc/sysv/consts/o.h"
|
||||||
#include "libc/sysv/errfuns.h"
|
#include "libc/sysv/errfuns.h"
|
||||||
#include "libc/thread/thread.h"
|
#include "libc/thread/thread.h"
|
||||||
|
@ -307,21 +310,49 @@ static textwindows int sys_fcntl_nt_dupfd(int fd, int cmd, int start) {
|
||||||
return sys_dup_nt(fd, -1, (cmd == F_DUPFD_CLOEXEC ? O_CLOEXEC : 0), start);
|
return sys_dup_nt(fd, -1, (cmd == F_DUPFD_CLOEXEC ? O_CLOEXEC : 0), start);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static textwindows int sys_fcntl_nt_setfl(int fd, unsigned *flags, unsigned arg,
|
||||||
|
unsigned supported) {
|
||||||
|
unsigned old, neu, changed, other, allowed;
|
||||||
|
old = *flags & supported;
|
||||||
|
other = *flags & ~supported;
|
||||||
|
neu = arg & supported;
|
||||||
|
changed = old ^ neu;
|
||||||
|
// you may change the following access mode flags:
|
||||||
|
//
|
||||||
|
// - O_NONBLOCK make read() raise EAGAIN
|
||||||
|
// - O_NDELAY same thing as O_NONBLOCK
|
||||||
|
//
|
||||||
|
allowed = O_NONBLOCK;
|
||||||
|
if (changed & ~allowed) {
|
||||||
|
// the following access mode flags are supported, but it's currently
|
||||||
|
// not possible to change them on windows.
|
||||||
|
//
|
||||||
|
// - O_APPEND tried to support but failed
|
||||||
|
// - O_RANDOM use posix_fadvise() instead
|
||||||
|
// - O_SEQUENTIAL use posix_fadvise() instead
|
||||||
|
// - O_DIRECT possibly in future?
|
||||||
|
// - O_DSYNC possibly in future?
|
||||||
|
// - O_RSYNC possibly in future?
|
||||||
|
// - O_SYNC possibly in future?
|
||||||
|
//
|
||||||
|
return enotsup();
|
||||||
|
}
|
||||||
|
// 1. ignore flags that aren't access mode flags
|
||||||
|
// 2. return zero if nothing's changed
|
||||||
|
*flags = other | neu;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
textwindows int sys_fcntl_nt(int fd, int cmd, uintptr_t arg) {
|
textwindows int sys_fcntl_nt(int fd, int cmd, uintptr_t arg) {
|
||||||
int rc;
|
int rc;
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
|
int access_mode_flags = O_ACCMODE | O_APPEND | O_ASYNC | O_DIRECT |
|
||||||
|
O_NOATIME | O_NONBLOCK | O_RANDOM | O_SEQUENTIAL;
|
||||||
if (__isfdkind(fd, kFdFile) || __isfdkind(fd, kFdSocket)) {
|
if (__isfdkind(fd, kFdFile) || __isfdkind(fd, kFdSocket)) {
|
||||||
if (cmd == F_GETFL) {
|
if (cmd == F_GETFL) {
|
||||||
rc = g_fds.p[fd].flags &
|
rc = g_fds.p[fd].flags & access_mode_flags;
|
||||||
(O_ACCMODE | O_APPEND | O_ASYNC | O_DIRECT | O_NOATIME | O_NONBLOCK |
|
|
||||||
O_RANDOM | O_SEQUENTIAL);
|
|
||||||
} else if (cmd == F_SETFL) {
|
} else if (cmd == F_SETFL) {
|
||||||
// O_APPEND doesn't appear to be tunable at cursory glance
|
rc = sys_fcntl_nt_setfl(fd, &g_fds.p[fd].flags, arg, access_mode_flags);
|
||||||
// O_NONBLOCK might require we start doing all i/o in threads
|
|
||||||
// O_DSYNC / O_RSYNC / O_SYNC maybe if we fsync() everything
|
|
||||||
// O_DIRECT | O_RANDOM | O_SEQUENTIAL | O_NDELAY possible but
|
|
||||||
// not worth it.
|
|
||||||
rc = enosys();
|
|
||||||
} else if (cmd == F_GETFD) {
|
} else if (cmd == F_GETFD) {
|
||||||
if (g_fds.p[fd].flags & O_CLOEXEC) {
|
if (g_fds.p[fd].flags & O_CLOEXEC) {
|
||||||
rc = FD_CLOEXEC;
|
rc = FD_CLOEXEC;
|
||||||
|
|
|
@ -26,9 +26,15 @@
|
||||||
// Applies file descriptor fixups on XNU or old Linux.
|
// Applies file descriptor fixups on XNU or old Linux.
|
||||||
// See __fixupnewsockfd() for socket file descriptors.
|
// See __fixupnewsockfd() for socket file descriptors.
|
||||||
int __fixupnewfd(int fd, int flags) {
|
int __fixupnewfd(int fd, int flags) {
|
||||||
|
int file_mode;
|
||||||
if (fd != -1) {
|
if (fd != -1) {
|
||||||
if (flags & O_CLOEXEC) {
|
if (flags & O_CLOEXEC) {
|
||||||
_npassert(!__sys_fcntl(fd, F_SETFD, FD_CLOEXEC));
|
_unassert((file_mode = __sys_fcntl(fd, F_GETFD)) != -1);
|
||||||
|
_unassert(!__sys_fcntl(fd, F_SETFD, file_mode | FD_CLOEXEC));
|
||||||
|
}
|
||||||
|
if (flags & O_NONBLOCK) {
|
||||||
|
_unassert((file_mode = __sys_fcntl(fd, F_GETFL)) != -1);
|
||||||
|
_unassert(!__sys_fcntl(fd, F_SETFL, file_mode | O_NONBLOCK));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return fd;
|
return fd;
|
||||||
|
|
|
@ -76,6 +76,6 @@ int getdomainname(char *name, size_t len) {
|
||||||
if (!rc && len && !strcmp(name, "(none)")) {
|
if (!rc && len && !strcmp(name, "(none)")) {
|
||||||
name[0] = 0;
|
name[0] = 0;
|
||||||
}
|
}
|
||||||
STRACE("getdomainname([%#.*s], %'zu) → %d% m", len, name, len, rc);
|
STRACE("getdomainname([%#.*s], %'zu) → %d% m", (int)len, name, len, rc);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,6 +71,6 @@ int gethostname(char *name, size_t len) {
|
||||||
} else {
|
} else {
|
||||||
rc = enosys();
|
rc = enosys();
|
||||||
}
|
}
|
||||||
STRACE("gethostname([%#.*s], %'zu) → %d% m", len, name, len, rc);
|
STRACE("gethostname([%#.*s], %'zu) → %d% m", (int)len, name, len, rc);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -558,34 +558,6 @@ static int ioctl_siocgifflags(int fd, void *arg) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets "close on exec" on file descriptor the fast way.
|
|
||||||
*
|
|
||||||
* @see ioctl(fd, FIOCLEX, 0) dispatches here
|
|
||||||
*/
|
|
||||||
static int ioctl_fioclex(int fd, int req) {
|
|
||||||
int rc;
|
|
||||||
if (fd >= 0) {
|
|
||||||
if (IsWindows() || (fd < g_fds.n && g_fds.p[fd].kind == kFdZip)) {
|
|
||||||
if (__isfdopen(fd)) {
|
|
||||||
if (req == FIOCLEX) {
|
|
||||||
g_fds.p[fd].flags |= O_CLOEXEC;
|
|
||||||
} else {
|
|
||||||
g_fds.p[fd].flags &= ~O_CLOEXEC;
|
|
||||||
}
|
|
||||||
rc = 0;
|
|
||||||
} else {
|
|
||||||
rc = ebadf();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
rc = sys_ioctl(fd, req);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
rc = einval();
|
|
||||||
}
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Performs special i/o operation on file descriptor.
|
* Performs special i/o operation on file descriptor.
|
||||||
*
|
*
|
||||||
|
@ -618,17 +590,6 @@ static int ioctl_fioclex(int fd, int req) {
|
||||||
* - `TIOCNXCL` to give up exclusive mode on terminal. Only
|
* - `TIOCNXCL` to give up exclusive mode on terminal. Only
|
||||||
* available on UNIX.
|
* available on UNIX.
|
||||||
*
|
*
|
||||||
* - `FIOCLEX` sets the `O_CLOEXEC` state (no arg) noting that this
|
|
||||||
* polyfill may be removed in the future, and code should migrate
|
|
||||||
* to the equivalent fcntl() api.
|
|
||||||
*
|
|
||||||
* - `FIONBIO` sets the `O_NONBLOCK` state (arg is `int *enabled`)
|
|
||||||
* which is supported on Windows for sockets.
|
|
||||||
*
|
|
||||||
* - `FIONCLEX` clears the `O_CLOEXEC` state (no arg) noting that
|
|
||||||
* this polyfill may be removed in the future, and code should
|
|
||||||
* migrate to the equivalent fcntl() api.
|
|
||||||
*
|
|
||||||
* - `SIOCGIFCONF` takes an struct ifconf object of a given size,
|
* - `SIOCGIFCONF` takes an struct ifconf object of a given size,
|
||||||
* whose arg is `struct ifconf *`. It implements the Linux style
|
* whose arg is `struct ifconf *`. It implements the Linux style
|
||||||
* and modifies the following:
|
* and modifies the following:
|
||||||
|
@ -647,6 +608,9 @@ static int ioctl_fioclex(int fd, int req) {
|
||||||
* network broadcast addr. This data structure should be obtained
|
* network broadcast addr. This data structure should be obtained
|
||||||
* by calling `SIOCGIFCONF`.
|
* by calling `SIOCGIFCONF`.
|
||||||
*
|
*
|
||||||
|
* - `FIONBIO` isn't polyfilled; use `fcntl(F_SETFL, O_NONBLOCK)`
|
||||||
|
* - `FIOCLEX` isn't polyfilled; use `fcntl(F_SETFD, FD_CLOEXEC)`
|
||||||
|
* - `FIONCLEX` isn't polyfilled; use `fcntl(F_SETFD, 0)`
|
||||||
* - `TCGETS` isn't polyfilled; use tcgetattr()
|
* - `TCGETS` isn't polyfilled; use tcgetattr()
|
||||||
* - `TCSETS` isn't polyfilled; use tcsetattr()
|
* - `TCSETS` isn't polyfilled; use tcsetattr()
|
||||||
* - `TCSETSW` isn't polyfilled; use tcsetattr()
|
* - `TCSETSW` isn't polyfilled; use tcsetattr()
|
||||||
|
@ -673,10 +637,6 @@ int ioctl(int fd, unsigned long request, ...) {
|
||||||
va_end(va);
|
va_end(va);
|
||||||
if (request == FIONBIO) {
|
if (request == FIONBIO) {
|
||||||
rc = ioctl_default(fd, request, arg);
|
rc = ioctl_default(fd, request, arg);
|
||||||
} else if (request == FIOCLEX) {
|
|
||||||
rc = ioctl_fioclex(fd, request);
|
|
||||||
} else if (request == FIONCLEX) {
|
|
||||||
rc = ioctl_fioclex(fd, request);
|
|
||||||
} else if (request == TIOCGWINSZ) {
|
} else if (request == TIOCGWINSZ) {
|
||||||
rc = tcgetwinsize(fd, arg);
|
rc = tcgetwinsize(fd, arg);
|
||||||
} else if (request == TIOCSWINSZ) {
|
} else if (request == TIOCSWINSZ) {
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
#include "libc/nt/runtime.h"
|
#include "libc/nt/runtime.h"
|
||||||
#include "libc/nt/struct/overlapped.h"
|
#include "libc/nt/struct/overlapped.h"
|
||||||
#include "libc/nt/synchronization.h"
|
#include "libc/nt/synchronization.h"
|
||||||
|
#include "libc/sysv/consts/o.h"
|
||||||
#include "libc/sysv/errfuns.h"
|
#include "libc/sysv/errfuns.h"
|
||||||
|
|
||||||
static textwindows ssize_t sys_read_nt_impl(struct Fd *fd, void *data,
|
static textwindows ssize_t sys_read_nt_impl(struct Fd *fd, void *data,
|
||||||
|
@ -51,6 +52,9 @@ static textwindows ssize_t sys_read_nt_impl(struct Fd *fd, void *data,
|
||||||
if (SleepEx(__SIG_POLLING_INTERVAL_MS, true) == kNtWaitIoCompletion) {
|
if (SleepEx(__SIG_POLLING_INTERVAL_MS, true) == kNtWaitIoCompletion) {
|
||||||
POLLTRACE("IOCP EINTR");
|
POLLTRACE("IOCP EINTR");
|
||||||
}
|
}
|
||||||
|
if (fd->flags & O_NONBLOCK) {
|
||||||
|
return eagain();
|
||||||
|
}
|
||||||
if (_check_interrupts(true, g_fds.p)) {
|
if (_check_interrupts(true, g_fds.p)) {
|
||||||
POLLTRACE("sys_read_nt interrupted");
|
POLLTRACE("sys_read_nt interrupted");
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
@ -56,6 +56,6 @@ ssize_t readlinkat(int dirfd, const char *path, char *buf, size_t bufsiz) {
|
||||||
bytes = sys_readlinkat_nt(dirfd, path, buf, bufsiz);
|
bytes = sys_readlinkat_nt(dirfd, path, buf, bufsiz);
|
||||||
}
|
}
|
||||||
STRACE("readlinkat(%s, %#s, [%#.*s]) → %d% m", DescribeDirfd(dirfd), path,
|
STRACE("readlinkat(%s, %#s, [%#.*s]) → %d% m", DescribeDirfd(dirfd), path,
|
||||||
MAX(0, bytes), buf, bytes);
|
(int)MAX(0, bytes), buf, bytes);
|
||||||
return bytes;
|
return bytes;
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,6 +42,7 @@ unsigned __wincrash(struct NtExceptionPointers *ep) {
|
||||||
ucontext_t ctx;
|
ucontext_t ctx;
|
||||||
struct CosmoTib *tib;
|
struct CosmoTib *tib;
|
||||||
static bool noreentry;
|
static bool noreentry;
|
||||||
|
noreentry = true;
|
||||||
|
|
||||||
if ((tib = __tls_enabled ? __get_tls_privileged() : 0)) {
|
if ((tib = __tls_enabled ? __get_tls_privileged() : 0)) {
|
||||||
if (~tib->tib_flags & TIB_FLAG_WINCRASHING) {
|
if (~tib->tib_flags & TIB_FLAG_WINCRASHING) {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
│ Copyright 2023 Justine Alexandra Roberts Tunney │
|
||||||
│ │
|
│ │
|
||||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||||
│ any purpose with or without fee is hereby granted, provided that the │
|
│ any purpose with or without fee is hereby granted, provided that the │
|
||||||
|
@ -16,21 +16,23 @@
|
||||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/dce.h"
|
#include "libc/calls/syscall_support-nt.internal.h"
|
||||||
#include "libc/sock/internal.h"
|
#include "libc/intrin/describentoverlapped.internal.h"
|
||||||
#include "libc/sock/struct/sockaddr.internal.h"
|
#include "libc/intrin/strace.internal.h"
|
||||||
|
#include "libc/nt/struct/overlapped.h"
|
||||||
|
#include "libc/nt/thread.h"
|
||||||
|
#include "libc/nt/thunk/msabi.h"
|
||||||
|
|
||||||
int sys_accept(int server, void *addr, uint32_t *addrsize) {
|
__msabi extern typeof(CancelIoEx) *const __imp_CancelIoEx;
|
||||||
int client;
|
|
||||||
uint32_t size;
|
/**
|
||||||
union sockaddr_storage_bsd bsd;
|
* Cancels Windows i/o operation.
|
||||||
if (!IsBsd()) {
|
*/
|
||||||
client = __sys_accept(server, addr, addrsize, 0);
|
bool32 CancelIoEx(int64_t hFile, struct NtOverlapped *opt_lpOverlapped) {
|
||||||
} else {
|
bool32 ok;
|
||||||
size = sizeof(bsd);
|
ok = __imp_CancelIoEx(hFile, opt_lpOverlapped);
|
||||||
if ((client = __sys_accept(server, &bsd, &size, 0)) != -1) {
|
if (!ok) __winerr();
|
||||||
sockaddr2linux(&bsd, size, addr, addrsize);
|
NTTRACE("CancelIoEx(%ld, %s) → %hhhd% m", hFile,
|
||||||
}
|
DescribeNtOverlapped(opt_lpOverlapped), ok);
|
||||||
}
|
return ok;
|
||||||
return client;
|
|
||||||
}
|
}
|
|
@ -146,6 +146,7 @@ o/$(MODE)/libc/intrin/exit1.greg.o \
|
||||||
o/$(MODE)/libc/intrin/wsarecv.o \
|
o/$(MODE)/libc/intrin/wsarecv.o \
|
||||||
o/$(MODE)/libc/intrin/wsarecvfrom.o \
|
o/$(MODE)/libc/intrin/wsarecvfrom.o \
|
||||||
o/$(MODE)/libc/intrin/createfile.o \
|
o/$(MODE)/libc/intrin/createfile.o \
|
||||||
|
o/$(MODE)/libc/intrin/cancelioex.o \
|
||||||
o/$(MODE)/libc/intrin/reopenfile.o \
|
o/$(MODE)/libc/intrin/reopenfile.o \
|
||||||
o/$(MODE)/libc/intrin/deletefile.o \
|
o/$(MODE)/libc/intrin/deletefile.o \
|
||||||
o/$(MODE)/libc/intrin/createpipe.o \
|
o/$(MODE)/libc/intrin/createpipe.o \
|
||||||
|
@ -175,6 +176,7 @@ o/$(MODE)/libc/intrin/mapviewoffileexnuma.o \
|
||||||
o/$(MODE)/libc/intrin/createfilemapping.o \
|
o/$(MODE)/libc/intrin/createfilemapping.o \
|
||||||
o/$(MODE)/libc/intrin/createfilemappingnuma.o \
|
o/$(MODE)/libc/intrin/createfilemappingnuma.o \
|
||||||
o/$(MODE)/libc/intrin/waitformultipleobjects.o \
|
o/$(MODE)/libc/intrin/waitformultipleobjects.o \
|
||||||
|
o/$(MODE)/libc/intrin/wsagetoverlappedresult.o \
|
||||||
o/$(MODE)/libc/intrin/generateconsolectrlevent.o \
|
o/$(MODE)/libc/intrin/generateconsolectrlevent.o \
|
||||||
o/$(MODE)/libc/intrin/wsawaitformultipleevents.o: private\
|
o/$(MODE)/libc/intrin/wsawaitformultipleevents.o: private\
|
||||||
CFLAGS += \
|
CFLAGS += \
|
||||||
|
|
|
@ -26,12 +26,14 @@
|
||||||
#include "libc/errno.h"
|
#include "libc/errno.h"
|
||||||
#include "libc/fmt/divmod10.internal.h"
|
#include "libc/fmt/divmod10.internal.h"
|
||||||
#include "libc/fmt/fmt.h"
|
#include "libc/fmt/fmt.h"
|
||||||
|
#include "libc/fmt/itoa.h"
|
||||||
#include "libc/fmt/magnumstrs.internal.h"
|
#include "libc/fmt/magnumstrs.internal.h"
|
||||||
#include "libc/intrin/asan.internal.h"
|
#include "libc/intrin/asan.internal.h"
|
||||||
#include "libc/intrin/asancodes.h"
|
#include "libc/intrin/asancodes.h"
|
||||||
#include "libc/intrin/atomic.h"
|
#include "libc/intrin/atomic.h"
|
||||||
#include "libc/intrin/bits.h"
|
#include "libc/intrin/bits.h"
|
||||||
#include "libc/intrin/cmpxchg.h"
|
#include "libc/intrin/cmpxchg.h"
|
||||||
|
#include "libc/intrin/kprintf.h"
|
||||||
#include "libc/intrin/likely.h"
|
#include "libc/intrin/likely.h"
|
||||||
#include "libc/intrin/nomultics.internal.h"
|
#include "libc/intrin/nomultics.internal.h"
|
||||||
#include "libc/intrin/safemacros.internal.h"
|
#include "libc/intrin/safemacros.internal.h"
|
||||||
|
@ -259,6 +261,7 @@ privileged static size_t kformat(char *b, size_t n, const char *fmt,
|
||||||
va_list va) {
|
va_list va) {
|
||||||
int si, y;
|
int si, y;
|
||||||
wint_t t, u;
|
wint_t t, u;
|
||||||
|
char errnum[12];
|
||||||
const char *abet;
|
const char *abet;
|
||||||
signed char type;
|
signed char type;
|
||||||
const char *s, *f;
|
const char *s, *f;
|
||||||
|
@ -539,6 +542,10 @@ privileged static size_t kformat(char *b, size_t n, const char *fmt,
|
||||||
} else {
|
} else {
|
||||||
type = 0;
|
type = 0;
|
||||||
s = _strerrno(e);
|
s = _strerrno(e);
|
||||||
|
if (!s) {
|
||||||
|
FormatInt32(errnum, e);
|
||||||
|
s = errnum;
|
||||||
|
}
|
||||||
goto FormatString;
|
goto FormatString;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -612,7 +619,7 @@ privileged static size_t kformat(char *b, size_t n, const char *fmt,
|
||||||
if (cols) --cols; // end quote
|
if (cols) --cols; // end quote
|
||||||
p = kemitquote(p, e, type, hash);
|
p = kemitquote(p, e, type, hash);
|
||||||
}
|
}
|
||||||
if (sign == ' ' && (!pdot || prec) && *s) {
|
if (sign == ' ' && (!pdot || prec) && s && *s) {
|
||||||
if (p < e) *p = ' ';
|
if (p < e) *p = ' ';
|
||||||
++p;
|
++p;
|
||||||
}
|
}
|
||||||
|
|
59
libc/intrin/wsagetoverlappedresult.c
Normal file
59
libc/intrin/wsagetoverlappedresult.c
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||||
|
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||||
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||||
|
│ Copyright 2023 Justine Alexandra Roberts Tunney │
|
||||||
|
│ │
|
||||||
|
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||||
|
│ any purpose with or without fee is hereby granted, provided that the │
|
||||||
|
│ above copyright notice and this permission notice appear in all copies. │
|
||||||
|
│ │
|
||||||
|
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||||
|
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||||
|
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||||
|
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||||
|
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||||
|
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||||
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "libc/errno.h"
|
||||||
|
#include "libc/intrin/describentoverlapped.internal.h"
|
||||||
|
#include "libc/intrin/kprintf.h"
|
||||||
|
#include "libc/intrin/strace.internal.h"
|
||||||
|
#include "libc/mem/alloca.h"
|
||||||
|
#include "libc/nt/thunk/msabi.h"
|
||||||
|
#include "libc/nt/winsock.h"
|
||||||
|
#include "libc/sock/internal.h"
|
||||||
|
|
||||||
|
__msabi extern typeof(WSAGetOverlappedResult)
|
||||||
|
*const __imp_WSAGetOverlappedResult;
|
||||||
|
|
||||||
|
static char *DescribeTransfer(char buf[16], bool32 ok, uint32_t *transfer) {
|
||||||
|
if (ok) {
|
||||||
|
ksnprintf(buf, 16, "%'u", *transfer);
|
||||||
|
return buf;
|
||||||
|
} else {
|
||||||
|
return "n/a";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets overlap i/o result.
|
||||||
|
*
|
||||||
|
* @return true on success, or false on failure
|
||||||
|
* @note this wrapper takes care of ABI, STRACE(), and __winsockerr()
|
||||||
|
*/
|
||||||
|
bool32 WSAGetOverlappedResult(uint64_t s,
|
||||||
|
const struct NtOverlapped *lpOverlapped,
|
||||||
|
uint32_t *out_lpcbTransfer, bool32 fWait,
|
||||||
|
uint32_t *out_lpdwFlags) {
|
||||||
|
bool32 ok;
|
||||||
|
ok = __imp_WSAGetOverlappedResult(s, lpOverlapped, out_lpcbTransfer, fWait,
|
||||||
|
out_lpdwFlags);
|
||||||
|
if (!ok) __winsockerr();
|
||||||
|
NTTRACE("WSAGetOverlappedResult(%ld, %s, [%s], %hhhd, [%#x]) → %hhhd% lm", s,
|
||||||
|
DescribeNtOverlapped(lpOverlapped),
|
||||||
|
DescribeTransfer(alloca(16), ok, out_lpcbTransfer), fWait,
|
||||||
|
*out_lpdwFlags, ok);
|
||||||
|
return ok;
|
||||||
|
}
|
|
@ -16,6 +16,7 @@
|
||||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "libc/assert.h"
|
||||||
#include "libc/calls/syscall_support-nt.internal.h"
|
#include "libc/calls/syscall_support-nt.internal.h"
|
||||||
#include "libc/intrin/describeflags.internal.h"
|
#include "libc/intrin/describeflags.internal.h"
|
||||||
#include "libc/intrin/describentoverlapped.internal.h"
|
#include "libc/intrin/describentoverlapped.internal.h"
|
||||||
|
@ -23,6 +24,7 @@
|
||||||
#include "libc/intrin/strace.internal.h"
|
#include "libc/intrin/strace.internal.h"
|
||||||
#include "libc/nt/thunk/msabi.h"
|
#include "libc/nt/thunk/msabi.h"
|
||||||
#include "libc/nt/winsock.h"
|
#include "libc/nt/winsock.h"
|
||||||
|
#include "libc/sock/internal.h"
|
||||||
|
|
||||||
__msabi extern typeof(WSARecv) *const __imp_WSARecv;
|
__msabi extern typeof(WSARecv) *const __imp_WSARecv;
|
||||||
|
|
||||||
|
@ -38,6 +40,12 @@ textwindows int WSARecv(
|
||||||
struct NtOverlapped *opt_inout_lpOverlapped,
|
struct NtOverlapped *opt_inout_lpOverlapped,
|
||||||
const NtWsaOverlappedCompletionRoutine opt_lpCompletionRoutine) {
|
const NtWsaOverlappedCompletionRoutine opt_lpCompletionRoutine) {
|
||||||
int rc;
|
int rc;
|
||||||
|
if (opt_inout_lpOverlapped) {
|
||||||
|
// Use NULL for this parameter if the lpOverlapped parameter is not
|
||||||
|
// NULL to avoid potentially erroneous results. This parameter can
|
||||||
|
// be NULL only if the lpOverlapped parameter is not NULL.
|
||||||
|
_unassert(!opt_out_lpNumberOfBytesRecvd);
|
||||||
|
}
|
||||||
#if defined(SYSDEBUG) && _NTTRACE
|
#if defined(SYSDEBUG) && _NTTRACE
|
||||||
uint32_t NumberOfBytesRecvd;
|
uint32_t NumberOfBytesRecvd;
|
||||||
if (opt_out_lpNumberOfBytesRecvd) {
|
if (opt_out_lpNumberOfBytesRecvd) {
|
||||||
|
@ -50,7 +58,7 @@ textwindows int WSARecv(
|
||||||
*opt_out_lpNumberOfBytesRecvd = NumberOfBytesRecvd;
|
*opt_out_lpNumberOfBytesRecvd = NumberOfBytesRecvd;
|
||||||
}
|
}
|
||||||
if (rc == -1) {
|
if (rc == -1) {
|
||||||
__winerr();
|
__winsockerr();
|
||||||
}
|
}
|
||||||
if (UNLIKELY(__strace > 0) && strace_enabled(0) > 0) {
|
if (UNLIKELY(__strace > 0) && strace_enabled(0) > 0) {
|
||||||
kprintf(STRACE_PROLOGUE "WSARecv(%lu, [", s);
|
kprintf(STRACE_PROLOGUE "WSARecv(%lu, [", s);
|
||||||
|
@ -66,7 +74,7 @@ textwindows int WSARecv(
|
||||||
opt_out_lpNumberOfBytesRecvd, inout_lpFlags,
|
opt_out_lpNumberOfBytesRecvd, inout_lpFlags,
|
||||||
opt_inout_lpOverlapped, opt_lpCompletionRoutine);
|
opt_inout_lpOverlapped, opt_lpCompletionRoutine);
|
||||||
if (rc == -1) {
|
if (rc == -1) {
|
||||||
__winerr();
|
__winsockerr();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
return rc;
|
return rc;
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
.text.windows
|
.text.windows
|
||||||
.ftrace1
|
.ftrace1
|
||||||
CancelIoEx:
|
__CancelIoEx:
|
||||||
.ftrace2
|
.ftrace2
|
||||||
#ifdef __x86_64__
|
#ifdef __x86_64__
|
||||||
push %rbp
|
push %rbp
|
||||||
|
@ -14,5 +14,5 @@ CancelIoEx:
|
||||||
mov x0,#0
|
mov x0,#0
|
||||||
ret
|
ret
|
||||||
#endif
|
#endif
|
||||||
.endfn CancelIoEx,globl
|
.endfn __CancelIoEx,globl
|
||||||
.previous
|
.previous
|
||||||
|
|
|
@ -98,7 +98,6 @@ imp 'CallNamedPipeA' CallNamedPipeA kernel32 110 7
|
||||||
imp 'CallbackMayRunLong' CallbackMayRunLong kernel32 0
|
imp 'CallbackMayRunLong' CallbackMayRunLong kernel32 0
|
||||||
imp 'CancelDeviceWakeupRequest' CancelDeviceWakeupRequest kernel32 113
|
imp 'CancelDeviceWakeupRequest' CancelDeviceWakeupRequest kernel32 113
|
||||||
imp 'CancelIo' CancelIo kernel32 0 1
|
imp 'CancelIo' CancelIo kernel32 0 1
|
||||||
imp 'CancelIoEx' CancelIoEx kernel32 0 2
|
|
||||||
imp 'CancelSynchronousIo' CancelSynchronousIo kernel32 0 1
|
imp 'CancelSynchronousIo' CancelSynchronousIo kernel32 0 1
|
||||||
imp 'CancelTimerQueueTimer' CancelTimerQueueTimer kernel32 118
|
imp 'CancelTimerQueueTimer' CancelTimerQueueTimer kernel32 118
|
||||||
imp 'CancelWaitableTimer' CancelWaitableTimer kernel32 0
|
imp 'CancelWaitableTimer' CancelWaitableTimer kernel32 0
|
||||||
|
@ -1097,6 +1096,7 @@ imp 'WriteProfileString' WriteProfileStringW kernel32 1575
|
||||||
imp 'WriteTapemark' WriteTapemark kernel32 1576
|
imp 'WriteTapemark' WriteTapemark kernel32 1576
|
||||||
imp 'ZombifyActCtx' ZombifyActCtx kernel32 0
|
imp 'ZombifyActCtx' ZombifyActCtx kernel32 0
|
||||||
imp 'ZombifyActCtxWorker' ZombifyActCtxWorker kernel32 1578
|
imp 'ZombifyActCtxWorker' ZombifyActCtxWorker kernel32 1578
|
||||||
|
imp '__CancelIoEx' CancelIoEx kernel32 0 2
|
||||||
imp '__CloseHandle' CloseHandle kernel32 0 1
|
imp '__CloseHandle' CloseHandle kernel32 0 1
|
||||||
imp '__CreateDirectory' CreateDirectoryW kernel32 0 2
|
imp '__CreateDirectory' CreateDirectoryW kernel32 0 2
|
||||||
imp '__CreateFile' CreateFileW kernel32 0 7
|
imp '__CreateFile' CreateFileW kernel32 0 7
|
||||||
|
@ -3228,7 +3228,6 @@ imp 'WSAEnumNetworkEvents' WSAEnumNetworkEvents ws2_32 64 3
|
||||||
imp 'WSAEnumProtocols' WSAEnumProtocolsW ws2_32 66 3
|
imp 'WSAEnumProtocols' WSAEnumProtocolsW ws2_32 66 3
|
||||||
imp 'WSAEventSelect' WSAEventSelect ws2_32 67 3
|
imp 'WSAEventSelect' WSAEventSelect ws2_32 67 3
|
||||||
imp 'WSAGetLastError' WSAGetLastError ws2_32 111 0
|
imp 'WSAGetLastError' WSAGetLastError ws2_32 111 0
|
||||||
imp 'WSAGetOverlappedResult' WSAGetOverlappedResult ws2_32 68 5
|
|
||||||
imp 'WSAGetQOSByName' WSAGetQOSByName ws2_32 69 3
|
imp 'WSAGetQOSByName' WSAGetQOSByName ws2_32 69 3
|
||||||
imp 'WSAGetServiceClassInfo' WSAGetServiceClassInfoW ws2_32 71 4
|
imp 'WSAGetServiceClassInfo' WSAGetServiceClassInfoW ws2_32 71 4
|
||||||
imp 'WSAGetServiceClassNameByClassId' WSAGetServiceClassNameByClassIdW ws2_32 73 3
|
imp 'WSAGetServiceClassNameByClassId' WSAGetServiceClassNameByClassIdW ws2_32 73 3
|
||||||
|
@ -3329,6 +3328,7 @@ imp '__WSARecvFrom' WSARecvFrom ws2_32 93 9
|
||||||
imp '__WSAWaitForMultipleEvents' WSAWaitForMultipleEvents ws2_32 124 5
|
imp '__WSAWaitForMultipleEvents' WSAWaitForMultipleEvents ws2_32 124 5
|
||||||
imp '__sys_recv_nt' recv ws2_32 16 4 # we're using WSARecvFrom()
|
imp '__sys_recv_nt' recv ws2_32 16 4 # we're using WSARecvFrom()
|
||||||
imp '__sys_send_nt' send ws2_32 19 4 # we're using WSASendTo()
|
imp '__sys_send_nt' send ws2_32 19 4 # we're using WSASendTo()
|
||||||
|
imp '__WSAGetOverlappedResult' WSAGetOverlappedResult ws2_32 68 5
|
||||||
|
|
||||||
# IPHLPAPI.DLL
|
# IPHLPAPI.DLL
|
||||||
#
|
#
|
||||||
|
|
|
@ -294,7 +294,7 @@ int32_t WSAStartup(uint16_t wVersionRequested, struct NtWsaData *lpWSAData)
|
||||||
paramsnonnull() dontdiscard;
|
paramsnonnull() dontdiscard;
|
||||||
|
|
||||||
int WSACleanup(void);
|
int WSACleanup(void);
|
||||||
int WSAGetLastError(void);
|
int WSAGetLastError(void) nosideeffect;
|
||||||
void WSASetLastError(int);
|
void WSASetLastError(int);
|
||||||
|
|
||||||
int __sys_bind_nt(uint64_t, const void *, int);
|
int __sys_bind_nt(uint64_t, const void *, int);
|
||||||
|
@ -343,6 +343,12 @@ int64_t WSAAccept(uint64_t s, struct sockaddr *out_addr,
|
||||||
const uint32_t *opt_dwCallbackData)
|
const uint32_t *opt_dwCallbackData)
|
||||||
paramsnonnull((2)) dontdiscard;
|
paramsnonnull((2)) dontdiscard;
|
||||||
|
|
||||||
|
bool32 AcceptEx(int64_t sListenSocket, int64_t sAcceptSocket,
|
||||||
|
void *out_lpOutputBuffer /*[recvlen+local+remoteaddrlen]*/,
|
||||||
|
uint32_t dwReceiveDataLength, uint32_t dwLocalAddressLength,
|
||||||
|
uint32_t dwRemoteAddressLength, uint32_t *out_lpdwBytesReceived,
|
||||||
|
struct NtOverlapped *inout_lpOverlapped);
|
||||||
|
|
||||||
int WSASend(uint64_t s, const struct NtIovec *lpBuffers, uint32_t dwBufferCount,
|
int WSASend(uint64_t s, const struct NtIovec *lpBuffers, uint32_t dwBufferCount,
|
||||||
uint32_t *opt_out_lpNumberOfBytesSent, uint32_t dwFlags,
|
uint32_t *opt_out_lpNumberOfBytesSent, uint32_t dwFlags,
|
||||||
struct NtOverlapped *opt_inout_lpOverlapped,
|
struct NtOverlapped *opt_inout_lpOverlapped,
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
.text.windows
|
.text.windows
|
||||||
.ftrace1
|
.ftrace1
|
||||||
WSAGetOverlappedResult:
|
__WSAGetOverlappedResult:
|
||||||
.ftrace2
|
.ftrace2
|
||||||
#ifdef __x86_64__
|
#ifdef __x86_64__
|
||||||
push %rbp
|
push %rbp
|
||||||
|
@ -14,5 +14,5 @@ WSAGetOverlappedResult:
|
||||||
mov x0,#0
|
mov x0,#0
|
||||||
ret
|
ret
|
||||||
#endif
|
#endif
|
||||||
.endfn WSAGetOverlappedResult,globl
|
.endfn __WSAGetOverlappedResult,globl
|
||||||
.previous
|
.previous
|
||||||
|
|
|
@ -58,8 +58,8 @@ int __inflate(void *out, size_t outsize, const void *in, size_t insize) {
|
||||||
} else {
|
} else {
|
||||||
rc = _puff(out, &outsize, in, &insize);
|
rc = _puff(out, &outsize, in, &insize);
|
||||||
}
|
}
|
||||||
STRACE("inflate([%#.*hhs%s], %'zu, %#.*hhs%s, %'zu) → %d", MIN(40, outsize),
|
STRACE("inflate([%#.*hhs%s], %'zu, %#.*hhs%s, %'zu) → %d",
|
||||||
out, outsize > 40 ? "..." : "", outsize, MIN(40, insize), in,
|
(int)MIN(40, outsize), out, outsize > 40 ? "..." : "", outsize,
|
||||||
insize > 40 ? "..." : "", insize, rc);
|
(int)MIN(40, insize), in, insize > 40 ? "..." : "", insize, rc);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,58 +17,109 @@
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/calls/internal.h"
|
#include "libc/calls/internal.h"
|
||||||
#include "libc/calls/sig.internal.h"
|
|
||||||
#include "libc/calls/state.internal.h"
|
#include "libc/calls/state.internal.h"
|
||||||
|
#include "libc/macros.internal.h"
|
||||||
#include "libc/mem/mem.h"
|
#include "libc/mem/mem.h"
|
||||||
#include "libc/nt/winsock.h"
|
#include "libc/nt/winsock.h"
|
||||||
#include "libc/sock/internal.h"
|
#include "libc/sock/internal.h"
|
||||||
|
#include "libc/sock/struct/sockaddr.h"
|
||||||
|
#include "libc/sock/struct/sockaddr.internal.h"
|
||||||
|
#include "libc/sock/struct/sockaddr6.h"
|
||||||
#include "libc/sock/syscall_fd.internal.h"
|
#include "libc/sock/syscall_fd.internal.h"
|
||||||
#include "libc/sysv/consts/fio.h"
|
#include "libc/str/str.h"
|
||||||
|
#include "libc/sysv/consts/af.h"
|
||||||
#include "libc/sysv/consts/o.h"
|
#include "libc/sysv/consts/o.h"
|
||||||
#include "libc/sysv/consts/poll.h"
|
|
||||||
#include "libc/sysv/consts/sock.h"
|
#include "libc/sysv/consts/sock.h"
|
||||||
#include "libc/sysv/errfuns.h"
|
|
||||||
|
|
||||||
textwindows int sys_accept_nt(struct Fd *fd, void *addr, uint32_t *addrsize,
|
union AcceptExAddr {
|
||||||
int flags) {
|
union sockaddr_storage_linux addr;
|
||||||
int64_t h;
|
char buf[sizeof(struct sockaddr_storage) + 16];
|
||||||
int rc, client, oflags;
|
};
|
||||||
struct SockFd *sockfd, *sockfd2;
|
|
||||||
sockfd = (struct SockFd *)fd->extra;
|
struct AcceptExBuffer {
|
||||||
if (_check_interrupts(true, g_fds.p)) return -1;
|
union AcceptExAddr local;
|
||||||
for (;;) {
|
union AcceptExAddr remote;
|
||||||
if (!WSAPoll(&(struct sys_pollfd_nt){fd->handle, POLLIN}, 1,
|
};
|
||||||
__SIG_POLLING_INTERVAL_MS)) {
|
|
||||||
if (_check_interrupts(true, g_fds.p)) {
|
static void CopyLinuxSockAddr(const union sockaddr_storage_linux *addr,
|
||||||
return eintr();
|
void *out_addr, uint32_t *inout_addrsize) {
|
||||||
}
|
uint32_t insize, outsize;
|
||||||
continue;
|
if (out_addr && inout_addrsize) {
|
||||||
|
if (addr->sa.sa_family == AF_INET) {
|
||||||
|
outsize = sizeof(struct sockaddr_in);
|
||||||
|
} else if (addr->sa.sa_family == AF_INET6) {
|
||||||
|
outsize = sizeof(struct sockaddr_in6);
|
||||||
|
} else if (addr->sa.sa_family == AF_UNIX) {
|
||||||
|
outsize = sizeof(addr->sun.sun_family) +
|
||||||
|
strnlen(addr->sun.sun_path, sizeof(addr->sun.sun_path)) + 1;
|
||||||
|
} else {
|
||||||
|
outsize = sizeof(union sockaddr_storage_linux);
|
||||||
}
|
}
|
||||||
if ((h = WSAAccept(fd->handle, addr, (int32_t *)addrsize, 0, 0)) != -1) {
|
insize = *inout_addrsize;
|
||||||
oflags = 0;
|
if (insize) bzero(out_addr, insize);
|
||||||
if (flags & SOCK_CLOEXEC) oflags |= O_CLOEXEC;
|
outsize = MIN(insize, outsize);
|
||||||
if (flags & SOCK_NONBLOCK) oflags |= O_NONBLOCK;
|
if (outsize) memcpy(out_addr, addr, outsize);
|
||||||
if ((!(flags & SOCK_NONBLOCK) ||
|
*inout_addrsize = outsize;
|
||||||
__sys_ioctlsocket_nt(h, FIONBIO, (uint32_t[]){1}) != -1) &&
|
|
||||||
(sockfd2 = calloc(1, sizeof(struct SockFd)))) {
|
|
||||||
__fds_lock();
|
|
||||||
if ((client = __reservefd_unlocked(-1)) != -1) {
|
|
||||||
sockfd2->family = sockfd->family;
|
|
||||||
sockfd2->type = sockfd->type;
|
|
||||||
sockfd2->protocol = sockfd->protocol;
|
|
||||||
g_fds.p[client].kind = kFdSocket;
|
|
||||||
g_fds.p[client].flags = oflags;
|
|
||||||
g_fds.p[client].mode = 0140666;
|
|
||||||
g_fds.p[client].handle = h;
|
|
||||||
g_fds.p[client].extra = (uintptr_t)sockfd2;
|
|
||||||
__fds_unlock();
|
|
||||||
return client;
|
|
||||||
}
|
|
||||||
__fds_unlock();
|
|
||||||
free(sockfd2);
|
|
||||||
}
|
|
||||||
__sys_closesocket_nt(h);
|
|
||||||
}
|
|
||||||
return __winsockerr();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
textwindows int sys_accept_nt(struct Fd *fd, void *out_addr,
|
||||||
|
uint32_t *inout_addrsize, int accept4_flags) {
|
||||||
|
int64_t handle;
|
||||||
|
int rc, client, oflags;
|
||||||
|
uint32_t bytes_received;
|
||||||
|
uint32_t completion_flags;
|
||||||
|
struct AcceptExBuffer buffer;
|
||||||
|
struct SockFd *sockfd, *sockfd2;
|
||||||
|
|
||||||
|
// deliver interrupt instead if any are pending
|
||||||
|
if (_check_interrupts(true, g_fds.p)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// creates resources for child socket
|
||||||
|
// inherit the listener configuration
|
||||||
|
sockfd = (struct SockFd *)fd->extra;
|
||||||
|
if (!(sockfd2 = malloc(sizeof(struct SockFd)))) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
memcpy(sockfd2, sockfd, sizeof(*sockfd));
|
||||||
|
if ((handle = WSASocket(sockfd2->family, sockfd2->type, sockfd2->protocol,
|
||||||
|
NULL, 0, kNtWsaFlagOverlapped)) == -1) {
|
||||||
|
free(sockfd2);
|
||||||
|
return __winsockerr();
|
||||||
|
}
|
||||||
|
|
||||||
|
// accept network connection
|
||||||
|
struct NtOverlapped overlapped = {.hEvent = WSACreateEvent()};
|
||||||
|
if (!AcceptEx(fd->handle, handle, &buffer, 0, sizeof(buffer.local),
|
||||||
|
sizeof(buffer.remote), &bytes_received, &overlapped)) {
|
||||||
|
sockfd = (struct SockFd *)fd->extra;
|
||||||
|
if (__wsablock(fd, &overlapped, &completion_flags, true,
|
||||||
|
sockfd->rcvtimeo) == -1) {
|
||||||
|
WSACloseEvent(overlapped.hEvent);
|
||||||
|
__sys_closesocket_nt(handle);
|
||||||
|
free(sockfd2);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WSACloseEvent(overlapped.hEvent);
|
||||||
|
|
||||||
|
// create file descriptor for new socket
|
||||||
|
// don't inherit the file open mode bits
|
||||||
|
oflags = 0;
|
||||||
|
if (accept4_flags & SOCK_CLOEXEC) oflags |= O_CLOEXEC;
|
||||||
|
if (accept4_flags & SOCK_NONBLOCK) oflags |= O_NONBLOCK;
|
||||||
|
__fds_lock();
|
||||||
|
client = __reservefd_unlocked(-1);
|
||||||
|
g_fds.p[client].kind = kFdSocket;
|
||||||
|
g_fds.p[client].flags = oflags;
|
||||||
|
g_fds.p[client].mode = 0140666;
|
||||||
|
g_fds.p[client].handle = handle;
|
||||||
|
g_fds.p[client].extra = (uintptr_t)sockfd2;
|
||||||
|
__fds_unlock();
|
||||||
|
|
||||||
|
// handoff information to caller;
|
||||||
|
CopyLinuxSockAddr(&buffer.remote.addr, out_addr, inout_addrsize);
|
||||||
|
return client;
|
||||||
|
}
|
||||||
|
|
|
@ -16,15 +16,20 @@
|
||||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "libc/assert.h"
|
||||||
|
#include "libc/calls/syscall-sysv.internal.h"
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
#include "libc/errno.h"
|
#include "libc/errno.h"
|
||||||
#include "libc/sock/internal.h"
|
#include "libc/sock/internal.h"
|
||||||
#include "libc/sock/sock.h"
|
#include "libc/sock/sock.h"
|
||||||
#include "libc/sock/struct/sockaddr.internal.h"
|
#include "libc/sock/struct/sockaddr.internal.h"
|
||||||
|
#include "libc/sysv/consts/f.h"
|
||||||
|
#include "libc/sysv/consts/fd.h"
|
||||||
|
#include "libc/sysv/consts/o.h"
|
||||||
|
#include "libc/sysv/consts/sock.h"
|
||||||
|
|
||||||
int sys_accept4(int server, void *addr, uint32_t *addrsize, int flags) {
|
int sys_accept4(int server, void *addr, uint32_t *addrsize, int flags) {
|
||||||
if (!flags) return sys_accept(server, addr, addrsize);
|
int olderr, client, file_mode;
|
||||||
int olderr, client;
|
|
||||||
union sockaddr_storage_bsd bsd;
|
union sockaddr_storage_bsd bsd;
|
||||||
uint32_t size = sizeof(bsd);
|
uint32_t size = sizeof(bsd);
|
||||||
void *out_addr = !IsBsd() ? addr : &bsd;
|
void *out_addr = !IsBsd() ? addr : &bsd;
|
||||||
|
@ -37,8 +42,17 @@ int sys_accept4(int server, void *addr, uint32_t *addrsize, int flags) {
|
||||||
errno = olderr;
|
errno = olderr;
|
||||||
demodernize = true;
|
demodernize = true;
|
||||||
TriedAndTrue:
|
TriedAndTrue:
|
||||||
client = __fixupnewsockfd(__sys_accept(server, out_addr, out_addrsize, 0),
|
if ((client = __sys_accept(server, out_addr, out_addrsize, 0)) != -1) {
|
||||||
flags);
|
// __sys_accept() has inconsistent flag inheritence across platforms
|
||||||
|
_unassert((file_mode = __sys_fcntl(client, F_GETFD)) != -1);
|
||||||
|
_unassert(!__sys_fcntl(client, F_SETFD,
|
||||||
|
((file_mode & ~FD_CLOEXEC) |
|
||||||
|
(flags & SOCK_CLOEXEC ? FD_CLOEXEC : 0))));
|
||||||
|
_unassert((file_mode = __sys_fcntl(client, F_GETFL)) != -1);
|
||||||
|
_unassert(!__sys_fcntl(client, F_SETFL,
|
||||||
|
((file_mode & ~O_NONBLOCK) |
|
||||||
|
(flags & SOCK_NONBLOCK ? O_NONBLOCK : 0))));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (client != -1 && IsBsd()) {
|
if (client != -1 && IsBsd()) {
|
||||||
sockaddr2linux(&bsd, size, addr, addrsize);
|
sockaddr2linux(&bsd, size, addr, addrsize);
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/assert.h"
|
#include "libc/assert.h"
|
||||||
|
#include "libc/intrin/bsr.h"
|
||||||
#include "libc/nt/winsock.h"
|
#include "libc/nt/winsock.h"
|
||||||
#include "libc/sock/internal.h"
|
#include "libc/sock/internal.h"
|
||||||
#include "libc/sock/syscall_fd.internal.h"
|
#include "libc/sock/syscall_fd.internal.h"
|
||||||
|
@ -29,7 +30,7 @@ textwindows int sys_connect_nt(struct Fd *fd, const void *addr,
|
||||||
sockfd = (struct SockFd *)fd->extra;
|
sockfd = (struct SockFd *)fd->extra;
|
||||||
_npassert(fd->kind == kFdSocket);
|
_npassert(fd->kind == kFdSocket);
|
||||||
return __winsockblock(
|
return __winsockblock(
|
||||||
fd->handle, FD_CONNECT_BIT,
|
fd->handle, _bsr(kNtFdConnect),
|
||||||
WSAConnect(fd->handle, addr, addrsize, NULL, NULL, NULL, NULL),
|
WSAConnect(fd->handle, addr, addrsize, NULL, NULL, NULL, NULL),
|
||||||
sockfd->rcvtimeo);
|
sockfd->rcvtimeo);
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,11 +21,6 @@
|
||||||
#include "libc/sysv/consts/o.h"
|
#include "libc/sysv/consts/o.h"
|
||||||
#include "libc/sysv/consts/sock.h"
|
#include "libc/sysv/consts/sock.h"
|
||||||
|
|
||||||
/**
|
|
||||||
* Applies non-atomic file descriptor fixups on XNU or ancient Linux.
|
|
||||||
*
|
|
||||||
* @param fd of -1 means no-op
|
|
||||||
*/
|
|
||||||
int __fixupnewsockfd(int fd, int flags) {
|
int __fixupnewsockfd(int fd, int flags) {
|
||||||
return __fixupnewfd(fd, (((flags & SOCK_CLOEXEC) ? O_CLOEXEC : 0) |
|
return __fixupnewfd(fd, (((flags & SOCK_CLOEXEC) ? O_CLOEXEC : 0) |
|
||||||
((flags & SOCK_NONBLOCK) ? O_NONBLOCK : 0)));
|
((flags & SOCK_NONBLOCK) ? O_NONBLOCK : 0)));
|
||||||
|
|
|
@ -11,18 +11,16 @@
|
||||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||||
COSMOPOLITAN_C_START_
|
COSMOPOLITAN_C_START_
|
||||||
|
|
||||||
#define FD_READ (1 << FD_READ_BIT)
|
#define kNtFdRead 1
|
||||||
#define FD_READ_BIT 0
|
#define kNtFdWrite 2
|
||||||
#define FD_WRITE (1 << FD_WRITE_BIT)
|
#define kNtFdOob 4
|
||||||
#define FD_WRITE_BIT 1
|
#define kNtFdAccept 8
|
||||||
#define FD_OOB (1 << FD_OOB_BIT)
|
#define kNtFdConnect 16
|
||||||
#define FD_OOB_BIT 2
|
#define kNtFdClose 32
|
||||||
#define FD_ACCEPT (1 << FD_ACCEPT_BIT)
|
#define kNtFdQos 64
|
||||||
#define FD_ACCEPT_BIT 3
|
#define kNtFdGroupQos 128
|
||||||
#define FD_CONNECT (1 << FD_CONNECT_BIT)
|
#define kNtFdRoutingInterfaceChange 256
|
||||||
#define FD_CONNECT_BIT 4
|
#define kNtFdAddressListChange 512
|
||||||
#define FD_CLOSE (1 << FD_CLOSE_BIT)
|
|
||||||
#define FD_CLOSE_BIT 5
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------------------*/
|
/* ------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
@ -34,17 +32,6 @@ struct SockFd {
|
||||||
int protocol;
|
int protocol;
|
||||||
uint32_t rcvtimeo;
|
uint32_t rcvtimeo;
|
||||||
uint32_t sndtimeo;
|
uint32_t sndtimeo;
|
||||||
bool32 (*__msabi ConnectEx)(int64_t s, const struct sockaddr *name,
|
|
||||||
int namelen, const void *opt_lpSendBuffer,
|
|
||||||
uint32_t dwSendDataLength,
|
|
||||||
uint32_t *out_lpdwBytesSent,
|
|
||||||
struct NtOverlapped *inout_lpOverlapped);
|
|
||||||
bool32 (*__msabi AcceptEx)(
|
|
||||||
int64_t sListenSocket, int64_t sAcceptSocket,
|
|
||||||
void *out_lpOutputBuffer /*[recvlen+local+remoteaddrlen]*/,
|
|
||||||
uint32_t dwReceiveDataLength, uint32_t dwLocalAddressLength,
|
|
||||||
uint32_t dwRemoteAddressLength, uint32_t *out_lpdwBytesReceived,
|
|
||||||
struct NtOverlapped *inout_lpOverlapped);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
errno_t __dos2errno(uint32_t) _Hide;
|
errno_t __dos2errno(uint32_t) _Hide;
|
||||||
|
@ -59,7 +46,6 @@ int32_t __sys_socket(int32_t, int32_t, int32_t) _Hide;
|
||||||
int32_t __sys_socketpair(int32_t, int32_t, int32_t, int32_t[2]) _Hide;
|
int32_t __sys_socketpair(int32_t, int32_t, int32_t, int32_t[2]) _Hide;
|
||||||
|
|
||||||
int32_t sys_accept4(int32_t, void *, uint32_t *, int) dontdiscard _Hide;
|
int32_t sys_accept4(int32_t, void *, uint32_t *, int) dontdiscard _Hide;
|
||||||
int32_t sys_accept(int32_t, void *, uint32_t *) _Hide;
|
|
||||||
int32_t sys_bind(int32_t, const void *, uint32_t) _Hide;
|
int32_t sys_bind(int32_t, const void *, uint32_t) _Hide;
|
||||||
int32_t sys_connect(int32_t, const void *, uint32_t) _Hide;
|
int32_t sys_connect(int32_t, const void *, uint32_t) _Hide;
|
||||||
int32_t sys_getsockopt(int32_t, int32_t, int32_t, void *, uint32_t *) _Hide;
|
int32_t sys_getsockopt(int32_t, int32_t, int32_t, void *, uint32_t *) _Hide;
|
||||||
|
@ -99,8 +85,6 @@ size_t __iovec2nt(struct NtIovec[hasatleast 16], const struct iovec *,
|
||||||
void WinSockInit(void) _Hide;
|
void WinSockInit(void) _Hide;
|
||||||
int64_t __winsockerr(void) nocallback _Hide;
|
int64_t __winsockerr(void) nocallback _Hide;
|
||||||
int __fixupnewsockfd(int, int) _Hide;
|
int __fixupnewsockfd(int, int) _Hide;
|
||||||
int __wsablock(int64_t, struct NtOverlapped *, uint32_t *, bool,
|
|
||||||
uint32_t) _Hide;
|
|
||||||
int64_t __winsockblock(int64_t, unsigned, int64_t, uint32_t) _Hide;
|
int64_t __winsockblock(int64_t, unsigned, int64_t, uint32_t) _Hide;
|
||||||
struct SockFd *_dupsockfd(struct SockFd *) _Hide;
|
struct SockFd *_dupsockfd(struct SockFd *) _Hide;
|
||||||
int64_t GetNtBaseSocket(int64_t) _Hide;
|
int64_t GetNtBaseSocket(int64_t) _Hide;
|
||||||
|
|
|
@ -16,9 +16,11 @@
|
||||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "libc/assert.h"
|
||||||
#include "libc/calls/internal.h"
|
#include "libc/calls/internal.h"
|
||||||
#include "libc/calls/struct/fd.internal.h"
|
#include "libc/calls/struct/fd.internal.h"
|
||||||
#include "libc/errno.h"
|
#include "libc/errno.h"
|
||||||
|
#include "libc/intrin/strace.internal.h"
|
||||||
#include "libc/nt/struct/iovec.h"
|
#include "libc/nt/struct/iovec.h"
|
||||||
#include "libc/nt/struct/overlapped.h"
|
#include "libc/nt/struct/overlapped.h"
|
||||||
#include "libc/nt/winsock.h"
|
#include "libc/nt/winsock.h"
|
||||||
|
@ -30,20 +32,24 @@ textwindows ssize_t sys_recv_nt(struct Fd *fd, const struct iovec *iov,
|
||||||
size_t iovlen, uint32_t flags) {
|
size_t iovlen, uint32_t flags) {
|
||||||
int err;
|
int err;
|
||||||
ssize_t rc;
|
ssize_t rc;
|
||||||
uint32_t got = 0;
|
uint32_t got = -666;
|
||||||
struct SockFd *sockfd;
|
struct SockFd *sockfd;
|
||||||
struct NtIovec iovnt[16];
|
struct NtIovec iovnt[16];
|
||||||
struct NtOverlapped overlapped = {.hEvent = WSACreateEvent()};
|
|
||||||
if (_check_interrupts(true, g_fds.p)) return -1;
|
if (_check_interrupts(true, g_fds.p)) return -1;
|
||||||
|
struct NtOverlapped overlapped = {.hEvent = WSACreateEvent()};
|
||||||
err = errno;
|
err = errno;
|
||||||
if (!WSARecv(fd->handle, iovnt, __iovec2nt(iovnt, iov, iovlen), &got, &flags,
|
if (!WSARecv(fd->handle, iovnt, __iovec2nt(iovnt, iov, iovlen), 0, &flags,
|
||||||
&overlapped, NULL)) {
|
&overlapped, 0)) {
|
||||||
rc = got;
|
if (WSAGetOverlappedResult(fd->handle, &overlapped, &got, false, &flags)) {
|
||||||
|
rc = got;
|
||||||
|
} else {
|
||||||
|
rc = -1;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
errno = err;
|
errno = err;
|
||||||
sockfd = (struct SockFd *)fd->extra;
|
sockfd = (struct SockFd *)fd->extra;
|
||||||
rc = __wsablock(fd->handle, &overlapped, &flags, true, sockfd->rcvtimeo);
|
rc = __wsablock(fd, &overlapped, &flags, true, sockfd->rcvtimeo);
|
||||||
}
|
}
|
||||||
WSACloseEvent(overlapped.hEvent);
|
_unassert(WSACloseEvent(overlapped.hEvent));
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,20 +31,23 @@ textwindows ssize_t sys_recvfrom_nt(struct Fd *fd, const struct iovec *iov,
|
||||||
uint32_t *opt_inout_srcaddrsize) {
|
uint32_t *opt_inout_srcaddrsize) {
|
||||||
int err;
|
int err;
|
||||||
ssize_t rc;
|
ssize_t rc;
|
||||||
uint32_t got = 0;
|
uint32_t got = -666;
|
||||||
struct SockFd *sockfd;
|
struct SockFd *sockfd;
|
||||||
struct NtIovec iovnt[16];
|
struct NtIovec iovnt[16];
|
||||||
struct NtOverlapped overlapped = {.hEvent = WSACreateEvent()};
|
|
||||||
if (_check_interrupts(true, g_fds.p)) return -1;
|
if (_check_interrupts(true, g_fds.p)) return -1;
|
||||||
|
struct NtOverlapped overlapped = {.hEvent = WSACreateEvent()};
|
||||||
err = errno;
|
err = errno;
|
||||||
if (!WSARecvFrom(fd->handle, iovnt, __iovec2nt(iovnt, iov, iovlen), &got,
|
if (!WSARecvFrom(fd->handle, iovnt, __iovec2nt(iovnt, iov, iovlen), 0, &flags,
|
||||||
&flags, opt_out_srcaddr, opt_inout_srcaddrsize, &overlapped,
|
opt_out_srcaddr, opt_inout_srcaddrsize, &overlapped, NULL)) {
|
||||||
NULL)) {
|
if (WSAGetOverlappedResult(fd->handle, &overlapped, &got, false, &flags)) {
|
||||||
rc = got;
|
rc = got;
|
||||||
|
} else {
|
||||||
|
rc = -1;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
errno = err;
|
errno = err;
|
||||||
sockfd = (struct SockFd *)fd->extra;
|
sockfd = (struct SockFd *)fd->extra;
|
||||||
rc = __wsablock(fd->handle, &overlapped, &flags, true, sockfd->rcvtimeo);
|
rc = __wsablock(fd, &overlapped, &flags, true, sockfd->rcvtimeo);
|
||||||
}
|
}
|
||||||
WSACloseEvent(overlapped.hEvent);
|
WSACloseEvent(overlapped.hEvent);
|
||||||
return rc;
|
return rc;
|
||||||
|
|
|
@ -21,23 +21,28 @@
|
||||||
#include "libc/nt/struct/overlapped.h"
|
#include "libc/nt/struct/overlapped.h"
|
||||||
#include "libc/nt/winsock.h"
|
#include "libc/nt/winsock.h"
|
||||||
#include "libc/sock/internal.h"
|
#include "libc/sock/internal.h"
|
||||||
|
#include "libc/sock/syscall_fd.internal.h"
|
||||||
#include "libc/sysv/errfuns.h"
|
#include "libc/sysv/errfuns.h"
|
||||||
|
|
||||||
textwindows ssize_t sys_send_nt(int fd, const struct iovec *iov, size_t iovlen,
|
textwindows ssize_t sys_send_nt(int fd, const struct iovec *iov, size_t iovlen,
|
||||||
uint32_t flags) {
|
uint32_t flags) {
|
||||||
ssize_t rc;
|
ssize_t rc;
|
||||||
uint32_t sent = 0;
|
uint32_t sent = -666;
|
||||||
struct SockFd *sockfd;
|
struct SockFd *sockfd;
|
||||||
struct NtIovec iovnt[16];
|
struct NtIovec iovnt[16];
|
||||||
struct NtOverlapped overlapped = {.hEvent = WSACreateEvent()};
|
|
||||||
if (_check_interrupts(true, g_fds.p)) return -1;
|
if (_check_interrupts(true, g_fds.p)) return -1;
|
||||||
if (!WSASend(g_fds.p[fd].handle, iovnt, __iovec2nt(iovnt, iov, iovlen), &sent,
|
struct NtOverlapped overlapped = {.hEvent = WSACreateEvent()};
|
||||||
|
if (!WSASend(g_fds.p[fd].handle, iovnt, __iovec2nt(iovnt, iov, iovlen), 0,
|
||||||
flags, &overlapped, NULL)) {
|
flags, &overlapped, NULL)) {
|
||||||
rc = sent;
|
if (WSAGetOverlappedResult(g_fds.p[fd].handle, &overlapped, &sent, false,
|
||||||
|
&flags)) {
|
||||||
|
rc = sent;
|
||||||
|
} else {
|
||||||
|
rc = -1;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
sockfd = (struct SockFd *)g_fds.p[fd].extra;
|
sockfd = (struct SockFd *)g_fds.p[fd].extra;
|
||||||
rc = __wsablock(g_fds.p[fd].handle, &overlapped, &flags, true,
|
rc = __wsablock(g_fds.p + fd, &overlapped, &flags, true, sockfd->sndtimeo);
|
||||||
sockfd->sndtimeo);
|
|
||||||
}
|
}
|
||||||
WSACloseEvent(overlapped.hEvent);
|
WSACloseEvent(overlapped.hEvent);
|
||||||
return rc;
|
return rc;
|
||||||
|
|
|
@ -65,11 +65,11 @@ static textwindows int SendfileBlock(int64_t handle,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!WSAGetOverlappedResult(handle, overlapped, &got, false, &flags)) {
|
if (WSAGetOverlappedResult(handle, overlapped, &got, false, &flags)) {
|
||||||
NTTRACE("WSAGetOverlappedResult failed %lm");
|
return got;
|
||||||
return __winsockerr();
|
} else {
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
return got;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static dontinline textwindows ssize_t sys_sendfile_nt(
|
static dontinline textwindows ssize_t sys_sendfile_nt(
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include "libc/nt/struct/overlapped.h"
|
#include "libc/nt/struct/overlapped.h"
|
||||||
#include "libc/nt/winsock.h"
|
#include "libc/nt/winsock.h"
|
||||||
#include "libc/sock/internal.h"
|
#include "libc/sock/internal.h"
|
||||||
|
#include "libc/sock/syscall_fd.internal.h"
|
||||||
#include "libc/sysv/errfuns.h"
|
#include "libc/sysv/errfuns.h"
|
||||||
|
|
||||||
textwindows ssize_t sys_sendto_nt(int fd, const struct iovec *iov,
|
textwindows ssize_t sys_sendto_nt(int fd, const struct iovec *iov,
|
||||||
|
@ -30,15 +31,19 @@ textwindows ssize_t sys_sendto_nt(int fd, const struct iovec *iov,
|
||||||
uint32_t sent = 0;
|
uint32_t sent = 0;
|
||||||
struct SockFd *sockfd;
|
struct SockFd *sockfd;
|
||||||
struct NtIovec iovnt[16];
|
struct NtIovec iovnt[16];
|
||||||
struct NtOverlapped overlapped = {.hEvent = WSACreateEvent()};
|
|
||||||
if (_check_interrupts(true, g_fds.p)) return -1;
|
if (_check_interrupts(true, g_fds.p)) return -1;
|
||||||
if (!WSASendTo(g_fds.p[fd].handle, iovnt, __iovec2nt(iovnt, iov, iovlen),
|
struct NtOverlapped overlapped = {.hEvent = WSACreateEvent()};
|
||||||
&sent, flags, opt_in_addr, in_addrsize, &overlapped, NULL)) {
|
if (!WSASendTo(g_fds.p[fd].handle, iovnt, __iovec2nt(iovnt, iov, iovlen), 0,
|
||||||
rc = sent;
|
flags, opt_in_addr, in_addrsize, &overlapped, NULL)) {
|
||||||
|
if (WSAGetOverlappedResult(g_fds.p[fd].handle, &overlapped, &sent, false,
|
||||||
|
&flags)) {
|
||||||
|
rc = sent;
|
||||||
|
} else {
|
||||||
|
rc = -1;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
sockfd = (struct SockFd *)g_fds.p[fd].extra;
|
sockfd = (struct SockFd *)g_fds.p[fd].extra;
|
||||||
rc = __wsablock(g_fds.p[fd].handle, &overlapped, &flags, true,
|
rc = __wsablock(g_fds.p + fd, &overlapped, &flags, true, sockfd->sndtimeo);
|
||||||
sockfd->sndtimeo);
|
|
||||||
}
|
}
|
||||||
WSACloseEvent(overlapped.hEvent);
|
WSACloseEvent(overlapped.hEvent);
|
||||||
return rc;
|
return rc;
|
||||||
|
|
|
@ -16,36 +16,50 @@
|
||||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "libc/calls/internal.h"
|
||||||
|
#include "libc/calls/struct/fd.internal.h"
|
||||||
#include "libc/calls/syscall-sysv.internal.h"
|
#include "libc/calls/syscall-sysv.internal.h"
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
#include "libc/intrin/strace.internal.h"
|
#include "libc/intrin/strace.internal.h"
|
||||||
#include "libc/nt/winsock.h"
|
#include "libc/nt/winsock.h"
|
||||||
|
#include "libc/sock/internal.h"
|
||||||
#include "libc/sock/sock.h"
|
#include "libc/sock/sock.h"
|
||||||
#include "libc/sysv/consts/sio.h"
|
#include "libc/sysv/errfuns.h"
|
||||||
|
|
||||||
static textwindows int sockatmark_nt(int64_t fd) {
|
static textwindows int sockatmark_nt(int fd, unsigned long magnum) {
|
||||||
bool32 res;
|
bool32 res;
|
||||||
|
int64_t hand;
|
||||||
uint32_t bytes;
|
uint32_t bytes;
|
||||||
if (WSAIoctl(fd, SIOCATMARK, 0, 0, &res, sizeof(res), &bytes, 0, 0) != -1) {
|
if (fd >= g_fds.n) return ebadf();
|
||||||
return !res;
|
if (g_fds.p[fd].kind != kFdSocket) return einval();
|
||||||
} else {
|
hand = g_fds.p[fd].handle;
|
||||||
return -1;
|
if (WSAIoctl(hand, magnum, 0, 0, &res, sizeof(res), &bytes, 0, 0) == -1) {
|
||||||
|
return __winsockerr();
|
||||||
}
|
}
|
||||||
|
return !res;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if out of band data is available on socket for reading.
|
* Returns true if out of band data is available on socket for reading.
|
||||||
*
|
*
|
||||||
* @return 1 if OOB'd, 0 if not, or -1 w/ errno
|
* @return 1 if OOB'd, 0 if not, or -1 w/ errno
|
||||||
|
* @raise EBADF if `fd` isn't an open file descriptor
|
||||||
|
* @raise EINVAL if `fd` isn't an appropriate file descriptor
|
||||||
*/
|
*/
|
||||||
int sockatmark(int fd) {
|
int sockatmark(int fd) {
|
||||||
int rc;
|
int rc;
|
||||||
|
unsigned long magnum;
|
||||||
|
if (IsLinux()) {
|
||||||
|
magnum = 0x8905; // SIOCATMARK (Linux only)
|
||||||
|
} else { //
|
||||||
|
magnum = 0x40047307; // SIOCATMARK (BSD, Windows)
|
||||||
|
}
|
||||||
if (!IsWindows()) {
|
if (!IsWindows()) {
|
||||||
if (sys_ioctl(fd, SIOCATMARK, &rc) == -1) {
|
if (sys_ioctl(fd, magnum, &rc) == -1) {
|
||||||
rc = -1;
|
rc = -1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
rc = sockatmark_nt(fd);
|
rc = sockatmark_nt(fd, magnum);
|
||||||
}
|
}
|
||||||
STRACE("sockatmark(%d) → %d% m", fd, rc);
|
STRACE("sockatmark(%d) → %d% m", fd, rc);
|
||||||
return rc;
|
return rc;
|
||||||
|
|
|
@ -24,7 +24,6 @@
|
||||||
#include "libc/nt/winsock.h"
|
#include "libc/nt/winsock.h"
|
||||||
#include "libc/sock/internal.h"
|
#include "libc/sock/internal.h"
|
||||||
#include "libc/sock/yoink.inc"
|
#include "libc/sock/yoink.inc"
|
||||||
#include "libc/sysv/consts/fio.h"
|
|
||||||
#include "libc/sysv/consts/ipproto.h"
|
#include "libc/sysv/consts/ipproto.h"
|
||||||
#include "libc/sysv/consts/o.h"
|
#include "libc/sysv/consts/o.h"
|
||||||
#include "libc/sysv/consts/so.h"
|
#include "libc/sysv/consts/so.h"
|
||||||
|
@ -52,13 +51,6 @@ textwindows int sys_socket_nt(int family, int type, int protocol) {
|
||||||
oflags = 0;
|
oflags = 0;
|
||||||
if (type & SOCK_CLOEXEC) oflags |= O_CLOEXEC;
|
if (type & SOCK_CLOEXEC) oflags |= O_CLOEXEC;
|
||||||
if (type & SOCK_NONBLOCK) oflags |= O_NONBLOCK;
|
if (type & SOCK_NONBLOCK) oflags |= O_NONBLOCK;
|
||||||
if (type & SOCK_NONBLOCK) {
|
|
||||||
if (__sys_ioctlsocket_nt(h, FIONBIO, (uint32_t[1]){1}) == -1) {
|
|
||||||
__sys_closesocket_nt(h);
|
|
||||||
__releasefd(fd);
|
|
||||||
return __winsockerr();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sockfd = calloc(1, sizeof(struct SockFd));
|
sockfd = calloc(1, sizeof(struct SockFd));
|
||||||
sockfd->family = family;
|
sockfd->family = family;
|
||||||
sockfd->type = truetype;
|
sockfd->type = truetype;
|
||||||
|
|
|
@ -22,29 +22,12 @@
|
||||||
#include "libc/sysv/consts/sock.h"
|
#include "libc/sysv/consts/sock.h"
|
||||||
|
|
||||||
int sys_socket(int family, int type, int protocol) {
|
int sys_socket(int family, int type, int protocol) {
|
||||||
static bool once, demodernize;
|
int sock, tf, e = errno;
|
||||||
int sock, olderr;
|
tf = SOCK_CLOEXEC | SOCK_NONBLOCK;
|
||||||
if (!once && (type & (SOCK_CLOEXEC | SOCK_NONBLOCK))) {
|
sock = __sys_socket(family, type, protocol);
|
||||||
if (IsXnu()) {
|
if (sock == -1 && (type & tf) && (errno == EINVAL || errno == EPROTOTYPE)) {
|
||||||
demodernize = true;
|
errno = e; // XNU/RHEL5/etc. don't support flags; see if removing helps
|
||||||
once = true;
|
sock = __fixupnewsockfd(__sys_socket(family, type & ~tf, protocol), type);
|
||||||
} else {
|
|
||||||
olderr = errno;
|
|
||||||
if ((sock = __sys_socket(family, type, protocol)) != -1) {
|
|
||||||
once = true;
|
|
||||||
return sock;
|
|
||||||
} else {
|
|
||||||
errno = olderr;
|
|
||||||
demodernize = true;
|
|
||||||
once = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!demodernize) {
|
|
||||||
return __sys_socket(family, type, protocol);
|
|
||||||
} else {
|
|
||||||
return __fixupnewsockfd(
|
|
||||||
__sys_socket(family, type & ~(SOCK_CLOEXEC | SOCK_NONBLOCK), protocol),
|
|
||||||
type);
|
|
||||||
}
|
}
|
||||||
|
return sock;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#define COSMOPOLITAN_LIBC_SOCK_SYSCALL_INTERNAL_H_
|
#define COSMOPOLITAN_LIBC_SOCK_SYSCALL_INTERNAL_H_
|
||||||
#include "libc/calls/struct/fd.internal.h"
|
#include "libc/calls/struct/fd.internal.h"
|
||||||
#include "libc/calls/struct/iovec.h"
|
#include "libc/calls/struct/iovec.h"
|
||||||
|
#include "libc/nt/struct/overlapped.h"
|
||||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||||
COSMOPOLITAN_C_START_
|
COSMOPOLITAN_C_START_
|
||||||
|
|
||||||
|
@ -18,6 +19,8 @@ int sys_shutdown_nt(struct Fd *, int) _Hide;
|
||||||
ssize_t sys_recv_nt(struct Fd *, const struct iovec *, size_t, uint32_t) _Hide;
|
ssize_t sys_recv_nt(struct Fd *, const struct iovec *, size_t, uint32_t) _Hide;
|
||||||
ssize_t sys_recvfrom_nt(struct Fd *, const struct iovec *, size_t, uint32_t,
|
ssize_t sys_recvfrom_nt(struct Fd *, const struct iovec *, size_t, uint32_t,
|
||||||
void *, uint32_t *) _Hide;
|
void *, uint32_t *) _Hide;
|
||||||
|
int __wsablock(struct Fd *, struct NtOverlapped *, uint32_t *, bool,
|
||||||
|
uint32_t) _Hide;
|
||||||
|
|
||||||
COSMOPOLITAN_C_END_
|
COSMOPOLITAN_C_END_
|
||||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||||
|
|
|
@ -16,24 +16,41 @@
|
||||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "libc/assert.h"
|
||||||
#include "libc/calls/internal.h"
|
#include "libc/calls/internal.h"
|
||||||
#include "libc/calls/sig.internal.h"
|
#include "libc/calls/sig.internal.h"
|
||||||
|
#include "libc/errno.h"
|
||||||
|
#include "libc/intrin/kprintf.h"
|
||||||
#include "libc/intrin/strace.internal.h"
|
#include "libc/intrin/strace.internal.h"
|
||||||
#include "libc/nt/enum/wait.h"
|
#include "libc/nt/enum/wait.h"
|
||||||
|
#include "libc/nt/enum/wsa.h"
|
||||||
#include "libc/nt/errors.h"
|
#include "libc/nt/errors.h"
|
||||||
|
#include "libc/nt/runtime.h"
|
||||||
|
#include "libc/nt/thread.h"
|
||||||
|
#include "libc/nt/winsock.h"
|
||||||
|
#include "libc/runtime/runtime.h"
|
||||||
#include "libc/sock/internal.h"
|
#include "libc/sock/internal.h"
|
||||||
#include "libc/sock/sock.h"
|
#include "libc/sock/sock.h"
|
||||||
|
#include "libc/sock/syscall_fd.internal.h"
|
||||||
|
#include "libc/str/str.h"
|
||||||
|
#include "libc/sysv/consts/o.h"
|
||||||
#include "libc/sysv/errfuns.h"
|
#include "libc/sysv/errfuns.h"
|
||||||
|
|
||||||
textwindows int __wsablock(int64_t handle, struct NtOverlapped *overlapped,
|
textwindows int __wsablock(struct Fd *fd, struct NtOverlapped *overlapped,
|
||||||
uint32_t *flags, bool restartable,
|
uint32_t *flags, bool restartable,
|
||||||
uint32_t timeout) {
|
uint32_t timeout) {
|
||||||
int rc;
|
int e, rc;
|
||||||
uint32_t i, got;
|
uint32_t i, got = -666;
|
||||||
if (WSAGetLastError() != kNtErrorIoPending) {
|
if (WSAGetLastError() != kNtErrorIoPending) {
|
||||||
NTTRACE("sock i/o failed %lm");
|
NTTRACE("sock i/o failed %s", strerror(errno));
|
||||||
return __winsockerr();
|
return __winsockerr();
|
||||||
}
|
}
|
||||||
|
if (fd->flags & O_NONBLOCK) {
|
||||||
|
e = errno;
|
||||||
|
_unassert(CancelIoEx(fd->handle, overlapped) ||
|
||||||
|
WSAGetLastError() == kNtErrorNotFound);
|
||||||
|
errno = e;
|
||||||
|
}
|
||||||
for (;;) {
|
for (;;) {
|
||||||
i = WSAWaitForMultipleEvents(1, &overlapped->hEvent, true,
|
i = WSAWaitForMultipleEvents(1, &overlapped->hEvent, true,
|
||||||
__SIG_POLLING_INTERVAL_MS, true);
|
__SIG_POLLING_INTERVAL_MS, true);
|
||||||
|
@ -46,6 +63,7 @@ textwindows int __wsablock(int64_t handle, struct NtOverlapped *overlapped,
|
||||||
}
|
}
|
||||||
if (timeout) {
|
if (timeout) {
|
||||||
if (timeout <= __SIG_POLLING_INTERVAL_MS) {
|
if (timeout <= __SIG_POLLING_INTERVAL_MS) {
|
||||||
|
NTTRACE("__wsablock timeout elapsed");
|
||||||
return eagain();
|
return eagain();
|
||||||
}
|
}
|
||||||
timeout -= __SIG_POLLING_INTERVAL_MS;
|
timeout -= __SIG_POLLING_INTERVAL_MS;
|
||||||
|
@ -54,9 +72,12 @@ textwindows int __wsablock(int64_t handle, struct NtOverlapped *overlapped,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!WSAGetOverlappedResult(handle, overlapped, &got, false, flags)) {
|
if (WSAGetOverlappedResult(fd->handle, overlapped, &got, false, flags)) {
|
||||||
NTTRACE("WSAGetOverlappedResult failed %lm");
|
return got;
|
||||||
return __winsockerr();
|
} else if ((fd->flags & O_NONBLOCK) &&
|
||||||
|
WSAGetLastError() == kNtErrorOperationAborted) {
|
||||||
|
return eagain();
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
return got;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -947,7 +947,6 @@ syscon ioctl FIONCLEX 0x5450 0x5450 0x20006602 0x20006602 0x20006602 0
|
||||||
#syscon ioctl FIONWRITE 0x0 0x0 0x0 0x0 0x40046677 0x0 0x0 -1 # [FreeBSD Generalization] bytes queued in FD's output buffer (same as TIOCOUTQ for TTY FDs; see also SO_SNDBUF)
|
#syscon ioctl FIONWRITE 0x0 0x0 0x0 0x0 0x40046677 0x0 0x0 -1 # [FreeBSD Generalization] bytes queued in FD's output buffer (same as TIOCOUTQ for TTY FDs; see also SO_SNDBUF)
|
||||||
#syscon ioctl FIONSPACE 0x0 0x0 0x0 0x0 0x40046676 0x0 0x0 -1 # [FreeBSD Generalization] capacity of FD's output buffer, e.g. equivalent to TIOCGSERIAL w/ UART
|
#syscon ioctl FIONSPACE 0x0 0x0 0x0 0x0 0x40046676 0x0 0x0 -1 # [FreeBSD Generalization] capacity of FD's output buffer, e.g. equivalent to TIOCGSERIAL w/ UART
|
||||||
syscon ioctl SIOCGIFCONF 0x8912 0x8912 0xc00c6924 0xc00c6924 0xc0106924 0xc0106924 0xc0106924 0
|
syscon ioctl SIOCGIFCONF 0x8912 0x8912 0xc00c6924 0xc00c6924 0xc0106924 0xc0106924 0xc0106924 0
|
||||||
syscon ioctl SIOCATMARK 0x8905 0x8905 0x40047307 0x40047307 0x40047307 0x40047307 0x40047307 0x40047307 # use sockatmark(); determines if oob is available; bsd consensus
|
|
||||||
syscon ioctl SIOCADDMULTI 0x8931 0x8931 0x80206931 0x80206931 0x80206931 0x80206931 0x80206931 0 # bsd consensus
|
syscon ioctl SIOCADDMULTI 0x8931 0x8931 0x80206931 0x80206931 0x80206931 0x80206931 0x80206931 0 # bsd consensus
|
||||||
syscon ioctl SIOCDELMULTI 0x8932 0x8932 0x80206932 0x80206932 0x80206932 0x80206932 0x80206932 0 # bsd consensus
|
syscon ioctl SIOCDELMULTI 0x8932 0x8932 0x80206932 0x80206932 0x80206932 0x80206932 0x80206932 0 # bsd consensus
|
||||||
syscon ioctl SIOCDIFADDR 0x8936 0x8936 0x80206919 0x80206919 0x80206919 0x80206919 0x80206919 0 # bsd consensus
|
syscon ioctl SIOCDIFADDR 0x8936 0x8936 0x80206919 0x80206919 0x80206919 0x80206919 0x80206919 0 # bsd consensus
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
#include "libc/sysv/consts/syscon.internal.h"
|
#include "libc/sysv/consts/syscon.internal.h"
|
||||||
.syscon sio,SIOCADDDLCI,0x8980,0x8980,0,0,0,0,0,0
|
.syscon ioctl,SIOCADDDLCI,0x8980,0x8980,0,0,0,0,0,0
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
#include "libc/sysv/consts/syscon.internal.h"
|
#include "libc/sysv/consts/syscon.internal.h"
|
||||||
.syscon sio,SIOCADDMULTI,0x8931,0x8931,0x80206931,0x80206931,0x80206931,0x80206931,0x80206931,0
|
.syscon ioctl,SIOCADDMULTI,0x8931,0x8931,0x80206931,0x80206931,0x80206931,0x80206931,0x80206931,0
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
#include "libc/sysv/consts/syscon.internal.h"
|
#include "libc/sysv/consts/syscon.internal.h"
|
||||||
.syscon sio,SIOCADDRT,0x890b,0x890b,0,0,0,0,0,0
|
.syscon ioctl,SIOCADDRT,0x890b,0x890b,0,0,0,0,0,0
|
||||||
|
|
|
@ -1,2 +0,0 @@
|
||||||
#include "libc/sysv/consts/syscon.internal.h"
|
|
||||||
.syscon sio,SIOCATMARK,0x8905,0x8905,0x40047307,0x40047307,0x40047307,0x40047307,0x40047307,0x40047307
|
|
|
@ -1,2 +1,2 @@
|
||||||
#include "libc/sysv/consts/syscon.internal.h"
|
#include "libc/sysv/consts/syscon.internal.h"
|
||||||
.syscon sio,SIOCDARP,0x8953,0x8953,0,0,0,0,0,0
|
.syscon ioctl,SIOCDARP,0x8953,0x8953,0,0,0,0,0,0
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
#include "libc/sysv/consts/syscon.internal.h"
|
#include "libc/sysv/consts/syscon.internal.h"
|
||||||
.syscon sio,SIOCDELDLCI,0x8981,0x8981,0,0,0,0,0,0
|
.syscon ioctl,SIOCDELDLCI,0x8981,0x8981,0,0,0,0,0,0
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
#include "libc/sysv/consts/syscon.internal.h"
|
#include "libc/sysv/consts/syscon.internal.h"
|
||||||
.syscon sio,SIOCDELMULTI,0x8932,0x8932,0x80206932,0x80206932,0x80206932,0x80206932,0x80206932,0
|
.syscon ioctl,SIOCDELMULTI,0x8932,0x8932,0x80206932,0x80206932,0x80206932,0x80206932,0x80206932,0
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
#include "libc/sysv/consts/syscon.internal.h"
|
#include "libc/sysv/consts/syscon.internal.h"
|
||||||
.syscon sio,SIOCDELRT,0x890c,0x890c,0,0,0,0,0,0
|
.syscon ioctl,SIOCDELRT,0x890c,0x890c,0,0,0,0,0,0
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
#include "libc/sysv/consts/syscon.internal.h"
|
#include "libc/sysv/consts/syscon.internal.h"
|
||||||
.syscon sio,SIOCDEVPRIVATE,0x89f0,0x89f0,0,0,0,0,0,0
|
.syscon ioctl,SIOCDEVPRIVATE,0x89f0,0x89f0,0,0,0,0,0,0
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
#include "libc/sysv/consts/syscon.internal.h"
|
#include "libc/sysv/consts/syscon.internal.h"
|
||||||
.syscon sio,SIOCDIFADDR,0x8936,0x8936,0x80206919,0x80206919,0x80206919,0x80206919,0x80206919,0
|
.syscon ioctl,SIOCDIFADDR,0x8936,0x8936,0x80206919,0x80206919,0x80206919,0x80206919,0x80206919,0
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
#include "libc/sysv/consts/syscon.internal.h"
|
#include "libc/sysv/consts/syscon.internal.h"
|
||||||
.syscon sio,SIOCDRARP,0x8960,0x8960,0,0,0,0,0,0
|
.syscon ioctl,SIOCDRARP,0x8960,0x8960,0,0,0,0,0,0
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
#include "libc/sysv/consts/syscon.internal.h"
|
#include "libc/sysv/consts/syscon.internal.h"
|
||||||
.syscon sio,SIOCGARP,0x8954,0x8954,0,0,0,0,0,0
|
.syscon ioctl,SIOCGARP,0x8954,0x8954,0,0,0,0,0,0
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
#include "libc/sysv/consts/syscon.internal.h"
|
#include "libc/sysv/consts/syscon.internal.h"
|
||||||
.syscon sio,SIOCGIFADDR,0x8915,0x8915,0xc0206921,0xc0206921,0xc0206921,0xc0206921,0xc0206921,0
|
.syscon ioctl,SIOCGIFADDR,0x8915,0x8915,0xc0206921,0xc0206921,0xc0206921,0xc0206921,0xc0206921,0
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
#include "libc/sysv/consts/syscon.internal.h"
|
#include "libc/sysv/consts/syscon.internal.h"
|
||||||
.syscon sio,SIOCGIFBR,0x8940,0x8940,0,0,0,0,0,0
|
.syscon ioctl,SIOCGIFBR,0x8940,0x8940,0,0,0,0,0,0
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
#include "libc/sysv/consts/syscon.internal.h"
|
#include "libc/sysv/consts/syscon.internal.h"
|
||||||
.syscon sio,SIOCGIFBRDADDR,0x8919,0x8919,0xc0206923,0xc0206923,0xc0206923,0xc0206923,0xc0206923,0
|
.syscon ioctl,SIOCGIFBRDADDR,0x8919,0x8919,0xc0206923,0xc0206923,0xc0206923,0xc0206923,0xc0206923,0
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
#include "libc/sysv/consts/syscon.internal.h"
|
#include "libc/sysv/consts/syscon.internal.h"
|
||||||
.syscon sio,SIOCGIFCONF,0x8912,0x8912,0xc00c6924,0xc00c6924,0xc0106924,0xc0106924,0xc0106924,0
|
.syscon ioctl,SIOCGIFCONF,0x8912,0x8912,0xc00c6924,0xc00c6924,0xc0106924,0xc0106924,0xc0106924,0
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
#include "libc/sysv/consts/syscon.internal.h"
|
#include "libc/sysv/consts/syscon.internal.h"
|
||||||
.syscon sio,SIOCGIFCOUNT,0x8938,0x8938,0,0,0,0,0,0
|
.syscon ioctl,SIOCGIFCOUNT,0x8938,0x8938,0,0,0,0,0,0
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
#include "libc/sysv/consts/syscon.internal.h"
|
#include "libc/sysv/consts/syscon.internal.h"
|
||||||
.syscon sio,SIOCGIFDSTADDR,0x8917,0x8917,0xc0206922,0xc0206922,0xc0206922,0xc0206922,0xc0206922,0
|
.syscon ioctl,SIOCGIFDSTADDR,0x8917,0x8917,0xc0206922,0xc0206922,0xc0206922,0xc0206922,0xc0206922,0
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
#include "libc/sysv/consts/syscon.internal.h"
|
#include "libc/sysv/consts/syscon.internal.h"
|
||||||
.syscon sio,SIOCGIFENCAP,0x8925,0x8925,0,0,0,0,0,0
|
.syscon ioctl,SIOCGIFENCAP,0x8925,0x8925,0,0,0,0,0,0
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
#include "libc/sysv/consts/syscon.internal.h"
|
#include "libc/sysv/consts/syscon.internal.h"
|
||||||
.syscon sio,SIOCGIFFLAGS,0x8913,0x8913,0xc0206911,0xc0206911,0xc0206911,0xc0206911,0xc0206911,0
|
.syscon ioctl,SIOCGIFFLAGS,0x8913,0x8913,0xc0206911,0xc0206911,0xc0206911,0xc0206911,0xc0206911,0
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
#include "libc/sysv/consts/syscon.internal.h"
|
#include "libc/sysv/consts/syscon.internal.h"
|
||||||
.syscon sio,SIOCGIFHWADDR,0x8927,0x8927,0,0,0,0,0,0
|
.syscon ioctl,SIOCGIFHWADDR,0x8927,0x8927,0,0,0,0,0,0
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
#include "libc/sysv/consts/syscon.internal.h"
|
#include "libc/sysv/consts/syscon.internal.h"
|
||||||
.syscon sio,SIOCGIFINDEX,0x8933,0x8933,0,0,0xc0206920,0,0,0
|
.syscon ioctl,SIOCGIFINDEX,0x8933,0x8933,0,0,0xc0206920,0,0,0
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
#include "libc/sysv/consts/syscon.internal.h"
|
#include "libc/sysv/consts/syscon.internal.h"
|
||||||
.syscon sio,SIOCGIFMAP,0x8970,0x8970,0,0,0,0,0,0
|
.syscon ioctl,SIOCGIFMAP,0x8970,0x8970,0,0,0,0,0,0
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
#include "libc/sysv/consts/syscon.internal.h"
|
#include "libc/sysv/consts/syscon.internal.h"
|
||||||
.syscon sio,SIOCGIFMEM,0x891f,0x891f,0,0,0,0,0,0
|
.syscon ioctl,SIOCGIFMEM,0x891f,0x891f,0,0,0,0,0,0
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
#include "libc/sysv/consts/syscon.internal.h"
|
#include "libc/sysv/consts/syscon.internal.h"
|
||||||
.syscon sio,SIOCGIFMETRIC,0x891d,0x891d,0xc0206917,0xc0206917,0xc0206917,0xc0206917,0xc0206917,0
|
.syscon ioctl,SIOCGIFMETRIC,0x891d,0x891d,0xc0206917,0xc0206917,0xc0206917,0xc0206917,0xc0206917,0
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
#include "libc/sysv/consts/syscon.internal.h"
|
#include "libc/sysv/consts/syscon.internal.h"
|
||||||
.syscon sio,SIOCGIFMTU,0x8921,0x8921,0xc0206933,0xc0206933,0xc0206933,0xc020697e,0xc020697e,0
|
.syscon ioctl,SIOCGIFMTU,0x8921,0x8921,0xc0206933,0xc0206933,0xc0206933,0xc020697e,0xc020697e,0
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
#include "libc/sysv/consts/syscon.internal.h"
|
#include "libc/sysv/consts/syscon.internal.h"
|
||||||
.syscon sio,SIOCGIFNAME,0x8910,0x8910,0,0,0,0,0,0
|
.syscon ioctl,SIOCGIFNAME,0x8910,0x8910,0,0,0,0,0,0
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
#include "libc/sysv/consts/syscon.internal.h"
|
#include "libc/sysv/consts/syscon.internal.h"
|
||||||
.syscon sio,SIOCGIFNETMASK,0x891b,0x891b,0xc0206925,0xc0206925,0xc0206925,0xc0206925,0xc0206925,0
|
.syscon ioctl,SIOCGIFNETMASK,0x891b,0x891b,0xc0206925,0xc0206925,0xc0206925,0xc0206925,0xc0206925,0
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
#include "libc/sysv/consts/syscon.internal.h"
|
#include "libc/sysv/consts/syscon.internal.h"
|
||||||
.syscon sio,SIOCGIFPFLAGS,0x8935,0x8935,0,0,0,0,0,0
|
.syscon ioctl,SIOCGIFPFLAGS,0x8935,0x8935,0,0,0,0,0,0
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
#include "libc/sysv/consts/syscon.internal.h"
|
#include "libc/sysv/consts/syscon.internal.h"
|
||||||
.syscon sio,SIOCGIFSLAVE,0x8929,0x8929,0,0,0,0,0,0
|
.syscon ioctl,SIOCGIFSLAVE,0x8929,0x8929,0,0,0,0,0,0
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
#include "libc/sysv/consts/syscon.internal.h"
|
#include "libc/sysv/consts/syscon.internal.h"
|
||||||
.syscon sio,SIOCGIFTXQLEN,0x8942,0x8942,0,0,0,0,0,0
|
.syscon ioctl,SIOCGIFTXQLEN,0x8942,0x8942,0,0,0,0,0,0
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
#include "libc/sysv/consts/syscon.internal.h"
|
#include "libc/sysv/consts/syscon.internal.h"
|
||||||
.syscon sio,SIOCGPGRP,0x8904,0x8904,0x40047309,0x40047309,0x40047309,0x40047309,0x40047309,0
|
.syscon ioctl,SIOCGPGRP,0x8904,0x8904,0x40047309,0x40047309,0x40047309,0x40047309,0x40047309,0
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
#include "libc/sysv/consts/syscon.internal.h"
|
#include "libc/sysv/consts/syscon.internal.h"
|
||||||
.syscon sio,SIOCGRARP,0x8961,0x8961,0,0,0,0,0,0
|
.syscon ioctl,SIOCGRARP,0x8961,0x8961,0,0,0,0,0,0
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
#include "libc/sysv/consts/syscon.internal.h"
|
#include "libc/sysv/consts/syscon.internal.h"
|
||||||
.syscon sio,SIOCGSTAMP,0x8906,0x8906,0,0,0,0,0,0
|
.syscon ioctl,SIOCGSTAMP,0x8906,0x8906,0,0,0,0,0,0
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
#include "libc/sysv/consts/syscon.internal.h"
|
#include "libc/sysv/consts/syscon.internal.h"
|
||||||
.syscon sio,SIOCGSTAMPNS,0x8907,0x8907,0,0,0,0,0,0
|
.syscon ioctl,SIOCGSTAMPNS,0x8907,0x8907,0,0,0,0,0,0
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
#include "libc/sysv/consts/syscon.internal.h"
|
#include "libc/sysv/consts/syscon.internal.h"
|
||||||
.syscon sio,SIOCPROTOPRIVATE,0x89e0,0x89e0,0,0,0,0,0,0
|
.syscon ioctl,SIOCPROTOPRIVATE,0x89e0,0x89e0,0,0,0,0,0,0
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
#include "libc/sysv/consts/syscon.internal.h"
|
#include "libc/sysv/consts/syscon.internal.h"
|
||||||
.syscon sio,SIOCRTMSG,0x890d,0x890d,0,0,0,0,0,0
|
.syscon ioctl,SIOCRTMSG,0x890d,0x890d,0,0,0,0,0,0
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
#include "libc/sysv/consts/syscon.internal.h"
|
#include "libc/sysv/consts/syscon.internal.h"
|
||||||
.syscon sio,SIOCSARP,0x8955,0x8955,0,0,0,0,0,0
|
.syscon ioctl,SIOCSARP,0x8955,0x8955,0,0,0,0,0,0
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
#include "libc/sysv/consts/syscon.internal.h"
|
#include "libc/sysv/consts/syscon.internal.h"
|
||||||
.syscon sio,SIOCSIFADDR,0x8916,0x8916,0x8020690c,0x8020690c,0x8020690c,0x8020690c,0x8020690c,0
|
.syscon ioctl,SIOCSIFADDR,0x8916,0x8916,0x8020690c,0x8020690c,0x8020690c,0x8020690c,0x8020690c,0
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
#include "libc/sysv/consts/syscon.internal.h"
|
#include "libc/sysv/consts/syscon.internal.h"
|
||||||
.syscon sio,SIOCSIFBR,0x8941,0x8941,0,0,0,0,0,0
|
.syscon ioctl,SIOCSIFBR,0x8941,0x8941,0,0,0,0,0,0
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
#include "libc/sysv/consts/syscon.internal.h"
|
#include "libc/sysv/consts/syscon.internal.h"
|
||||||
.syscon sio,SIOCSIFBRDADDR,0x891a,0x891a,0x80206913,0x80206913,0x80206913,0x80206913,0x80206913,0
|
.syscon ioctl,SIOCSIFBRDADDR,0x891a,0x891a,0x80206913,0x80206913,0x80206913,0x80206913,0x80206913,0
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
#include "libc/sysv/consts/syscon.internal.h"
|
#include "libc/sysv/consts/syscon.internal.h"
|
||||||
.syscon sio,SIOCSIFDSTADDR,0x8918,0x8918,0x8020690e,0x8020690e,0x8020690e,0x8020690e,0x8020690e,0
|
.syscon ioctl,SIOCSIFDSTADDR,0x8918,0x8918,0x8020690e,0x8020690e,0x8020690e,0x8020690e,0x8020690e,0
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
#include "libc/sysv/consts/syscon.internal.h"
|
#include "libc/sysv/consts/syscon.internal.h"
|
||||||
.syscon sio,SIOCSIFENCAP,0x8926,0x8926,0,0,0,0,0,0
|
.syscon ioctl,SIOCSIFENCAP,0x8926,0x8926,0,0,0,0,0,0
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
#include "libc/sysv/consts/syscon.internal.h"
|
#include "libc/sysv/consts/syscon.internal.h"
|
||||||
.syscon sio,SIOCSIFFLAGS,0x8914,0x8914,0x80206910,0x80206910,0x80206910,0x80206910,0x80206910,0
|
.syscon ioctl,SIOCSIFFLAGS,0x8914,0x8914,0x80206910,0x80206910,0x80206910,0x80206910,0x80206910,0
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
#include "libc/sysv/consts/syscon.internal.h"
|
#include "libc/sysv/consts/syscon.internal.h"
|
||||||
.syscon sio,SIOCSIFHWADDR,0x8924,0x8924,0,0,0,0,0,0
|
.syscon ioctl,SIOCSIFHWADDR,0x8924,0x8924,0,0,0,0,0,0
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
#include "libc/sysv/consts/syscon.internal.h"
|
#include "libc/sysv/consts/syscon.internal.h"
|
||||||
.syscon sio,SIOCSIFHWBROADCAST,0x8937,0x8937,0,0,0,0,0,0
|
.syscon ioctl,SIOCSIFHWBROADCAST,0x8937,0x8937,0,0,0,0,0,0
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
#include "libc/sysv/consts/syscon.internal.h"
|
#include "libc/sysv/consts/syscon.internal.h"
|
||||||
.syscon sio,SIOCSIFLINK,0x8911,0x8911,0,0,0,0,0,0
|
.syscon ioctl,SIOCSIFLINK,0x8911,0x8911,0,0,0,0,0,0
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
#include "libc/sysv/consts/syscon.internal.h"
|
#include "libc/sysv/consts/syscon.internal.h"
|
||||||
.syscon sio,SIOCSIFMAP,0x8971,0x8971,0,0,0,0,0,0
|
.syscon ioctl,SIOCSIFMAP,0x8971,0x8971,0,0,0,0,0,0
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
#include "libc/sysv/consts/syscon.internal.h"
|
#include "libc/sysv/consts/syscon.internal.h"
|
||||||
.syscon sio,SIOCSIFMEM,0x8920,0x8920,0,0,0,0,0,0
|
.syscon ioctl,SIOCSIFMEM,0x8920,0x8920,0,0,0,0,0,0
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
#include "libc/sysv/consts/syscon.internal.h"
|
#include "libc/sysv/consts/syscon.internal.h"
|
||||||
.syscon sio,SIOCSIFMETRIC,0x891e,0x891e,0x80206918,0x80206918,0x80206918,0x80206918,0x80206918,0
|
.syscon ioctl,SIOCSIFMETRIC,0x891e,0x891e,0x80206918,0x80206918,0x80206918,0x80206918,0x80206918,0
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
#include "libc/sysv/consts/syscon.internal.h"
|
#include "libc/sysv/consts/syscon.internal.h"
|
||||||
.syscon sio,SIOCSIFMTU,0x8922,0x8922,0x80206934,0x80206934,0x80206934,0x8020697f,0x8020697f,0
|
.syscon ioctl,SIOCSIFMTU,0x8922,0x8922,0x80206934,0x80206934,0x80206934,0x8020697f,0x8020697f,0
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
#include "libc/sysv/consts/syscon.internal.h"
|
#include "libc/sysv/consts/syscon.internal.h"
|
||||||
.syscon sio,SIOCSIFNAME,0x8923,0x8923,0,0,0x80206928,0,0,0
|
.syscon ioctl,SIOCSIFNAME,0x8923,0x8923,0,0,0x80206928,0,0,0
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
#include "libc/sysv/consts/syscon.internal.h"
|
#include "libc/sysv/consts/syscon.internal.h"
|
||||||
.syscon sio,SIOCSIFNETMASK,0x891c,0x891c,0x80206916,0x80206916,0x80206916,0x80206916,0x80206916,0
|
.syscon ioctl,SIOCSIFNETMASK,0x891c,0x891c,0x80206916,0x80206916,0x80206916,0x80206916,0x80206916,0
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
#include "libc/sysv/consts/syscon.internal.h"
|
#include "libc/sysv/consts/syscon.internal.h"
|
||||||
.syscon sio,SIOCSIFPFLAGS,0x8934,0x8934,0,0,0,0,0,0
|
.syscon ioctl,SIOCSIFPFLAGS,0x8934,0x8934,0,0,0,0,0,0
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
#include "libc/sysv/consts/syscon.internal.h"
|
#include "libc/sysv/consts/syscon.internal.h"
|
||||||
.syscon sio,SIOCSIFSLAVE,0x8930,0x8930,0,0,0,0,0,0
|
.syscon ioctl,SIOCSIFSLAVE,0x8930,0x8930,0,0,0,0,0,0
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
#include "libc/sysv/consts/syscon.internal.h"
|
#include "libc/sysv/consts/syscon.internal.h"
|
||||||
.syscon sio,SIOCSIFTXQLEN,0x8943,0x8943,0,0,0,0,0,0
|
.syscon ioctl,SIOCSIFTXQLEN,0x8943,0x8943,0,0,0,0,0,0
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
#include "libc/sysv/consts/syscon.internal.h"
|
#include "libc/sysv/consts/syscon.internal.h"
|
||||||
.syscon sio,SIOCSPGRP,0x8902,0x8902,0x80047308,0x80047308,0x80047308,0x80047308,0x80047308,0
|
.syscon ioctl,SIOCSPGRP,0x8902,0x8902,0x80047308,0x80047308,0x80047308,0x80047308,0x80047308,0
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
#include "libc/sysv/consts/syscon.internal.h"
|
#include "libc/sysv/consts/syscon.internal.h"
|
||||||
.syscon sio,SIOCSRARP,0x8962,0x8962,0,0,0,0,0,0
|
.syscon ioctl,SIOCSRARP,0x8962,0x8962,0,0,0,0,0,0
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
#include "libc/sysv/consts/syscon.internal.h"
|
#include "libc/sysv/consts/syscon.internal.h"
|
||||||
.syscon sio,SIOGIFINDEX,0x8933,0x8933,0,0,0,0,0,0
|
.syscon ioctl,SIOGIFINDEX,0x8933,0x8933,0,0,0,0,0,0
|
||||||
|
|
|
@ -3,16 +3,12 @@
|
||||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||||
COSMOPOLITAN_C_START_
|
COSMOPOLITAN_C_START_
|
||||||
|
|
||||||
extern const uint32_t FIOASYNC;
|
extern const uint32_t FIONREAD; /* one of the few encouraged ioctls */
|
||||||
extern const uint32_t FIOCLEX;
|
extern const uint32_t FIONBIO; /* use fcntl(fd, F_SETFL, O_NONBLOCK) */
|
||||||
extern const uint32_t FIONBIO;
|
extern const uint32_t FIOCLEX; /* use fcntl(fd, F_SETFD, FD_CLOEXEC) */
|
||||||
extern const uint32_t FIONCLEX;
|
extern const uint32_t FIONCLEX; /* use fcntl(fd, F_SETFD, 0) */
|
||||||
extern const uint32_t FIONREAD;
|
extern const uint32_t FIOASYNC; /* todo: fcntl(fd, F_SETOWN, pid) */
|
||||||
|
|
||||||
#define FIOASYNC FIOASYNC
|
|
||||||
#define FIOCLEX FIOCLEX
|
|
||||||
#define FIONBIO FIONBIO
|
|
||||||
#define FIONCLEX FIONCLEX
|
|
||||||
#define FIONREAD FIONREAD
|
#define FIONREAD FIONREAD
|
||||||
|
|
||||||
COSMOPOLITAN_C_END_
|
COSMOPOLITAN_C_END_
|
||||||
|
|
|
@ -6,7 +6,6 @@ COSMOPOLITAN_C_START_
|
||||||
extern const unsigned long SIOCADDDLCI;
|
extern const unsigned long SIOCADDDLCI;
|
||||||
extern const unsigned long SIOCADDMULTI;
|
extern const unsigned long SIOCADDMULTI;
|
||||||
extern const unsigned long SIOCADDRT;
|
extern const unsigned long SIOCADDRT;
|
||||||
extern const unsigned long SIOCATMARK; /* use sockatmark() */
|
|
||||||
extern const unsigned long SIOCDARP;
|
extern const unsigned long SIOCDARP;
|
||||||
extern const unsigned long SIOCDELDLCI;
|
extern const unsigned long SIOCDELDLCI;
|
||||||
extern const unsigned long SIOCDELMULTI;
|
extern const unsigned long SIOCDELMULTI;
|
||||||
|
|
|
@ -55,7 +55,7 @@ dos kNtErrorInvalidFunction EINVAL
|
||||||
dos kNtErrorNegativeSeek EINVAL
|
dos kNtErrorNegativeSeek EINVAL
|
||||||
dos kNtErrorInvalidNetname EADDRNOTAVAIL
|
dos kNtErrorInvalidNetname EADDRNOTAVAIL
|
||||||
dos kNtErrorInvalidUserBuffer EMSGSIZE
|
dos kNtErrorInvalidUserBuffer EMSGSIZE
|
||||||
dos kNtErrorIoPending EINPROGRESS
|
dos kNtErrorIoPending EINPROGRESS
|
||||||
dos kNtErrorLockViolation EAGAIN
|
dos kNtErrorLockViolation EAGAIN
|
||||||
dos kNtErrorMoreData EMSGSIZE
|
dos kNtErrorMoreData EMSGSIZE
|
||||||
dos kNtErrorNetnameDeleted ECONNABORTED
|
dos kNtErrorNetnameDeleted ECONNABORTED
|
||||||
|
|
|
@ -23,6 +23,15 @@
|
||||||
* Initializes pthread attributes.
|
* Initializes pthread attributes.
|
||||||
*
|
*
|
||||||
* @return 0 on success, or errno on error
|
* @return 0 on success, or errno on error
|
||||||
|
* @see pthread_attr_setdetachstate()
|
||||||
|
* @see pthread_attr_setsigmask_np()
|
||||||
|
* @see pthread_attr_setstack()
|
||||||
|
* @see pthread_attr_setstacksize()
|
||||||
|
* @see pthread_attr_setguardsize()
|
||||||
|
* @see pthread_attr_setschedparam()
|
||||||
|
* @see pthread_attr_setschedpolicy()
|
||||||
|
* @see pthread_attr_setinheritsched()
|
||||||
|
* @see pthread_attr_setscope()
|
||||||
*/
|
*/
|
||||||
errno_t pthread_attr_init(pthread_attr_t *attr) {
|
errno_t pthread_attr_init(pthread_attr_t *attr) {
|
||||||
*attr = (pthread_attr_t){
|
*attr = (pthread_attr_t){
|
||||||
|
|
127
test/libc/sock/nonblock_test.c
Normal file
127
test/libc/sock/nonblock_test.c
Normal file
|
@ -0,0 +1,127 @@
|
||||||
|
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||||
|
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||||
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||||
|
│ Copyright 2023 Justine Alexandra Roberts Tunney │
|
||||||
|
│ │
|
||||||
|
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||||
|
│ any purpose with or without fee is hereby granted, provided that the │
|
||||||
|
│ above copyright notice and this permission notice appear in all copies. │
|
||||||
|
│ │
|
||||||
|
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||||
|
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||||
|
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||||
|
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||||
|
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||||
|
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||||
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "libc/calls/calls.h"
|
||||||
|
#include "libc/errno.h"
|
||||||
|
#include "libc/intrin/strace.internal.h"
|
||||||
|
#include "libc/runtime/runtime.h"
|
||||||
|
#include "libc/runtime/syslib.internal.h"
|
||||||
|
#include "libc/sock/sock.h"
|
||||||
|
#include "libc/sock/struct/sockaddr.h"
|
||||||
|
#include "libc/sysv/consts/af.h"
|
||||||
|
#include "libc/sysv/consts/f.h"
|
||||||
|
#include "libc/sysv/consts/ipproto.h"
|
||||||
|
#include "libc/sysv/consts/limits.h"
|
||||||
|
#include "libc/sysv/consts/o.h"
|
||||||
|
#include "libc/sysv/consts/sock.h"
|
||||||
|
#include "libc/testlib/subprocess.h"
|
||||||
|
#include "libc/testlib/testlib.h"
|
||||||
|
#include "libc/thread/thread.h"
|
||||||
|
|
||||||
|
TEST(O_NONBLOCK, canBeSetBySocket_toMakeListenNonBlocking) {
|
||||||
|
int ws, pid;
|
||||||
|
char buf[16] = {0};
|
||||||
|
int64_t inoffset;
|
||||||
|
uint32_t addrsize = sizeof(struct sockaddr_in);
|
||||||
|
struct sockaddr_in addr = {
|
||||||
|
.sin_family = AF_INET,
|
||||||
|
.sin_addr.s_addr = htonl(0x7f000001),
|
||||||
|
};
|
||||||
|
pthread_spinlock_t *phaser = _mapshared(4096);
|
||||||
|
EXPECT_EQ(0, pthread_spin_lock(phaser + 0));
|
||||||
|
EXPECT_EQ(0, pthread_spin_lock(phaser + 1));
|
||||||
|
ASSERT_SYS(0, 3, socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, IPPROTO_TCP));
|
||||||
|
ASSERT_SYS(0, 0, bind(3, (struct sockaddr *)&addr, sizeof(addr)));
|
||||||
|
ASSERT_SYS(0, 0, getsockname(3, (struct sockaddr *)&addr, &addrsize));
|
||||||
|
ASSERT_SYS(0, 0, listen(3, SOMAXCONN));
|
||||||
|
SPAWN(fork);
|
||||||
|
ASSERT_SYS(EAGAIN, -1, accept(3, (struct sockaddr *)&addr, &addrsize));
|
||||||
|
EXPECT_EQ(0, pthread_spin_unlock(phaser + 0));
|
||||||
|
for (;;) {
|
||||||
|
int e = errno;
|
||||||
|
int fd = accept(3, (struct sockaddr *)&addr, &addrsize);
|
||||||
|
if (fd == -1 && errno == EAGAIN) {
|
||||||
|
errno = e;
|
||||||
|
usleep(1000);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ASSERT_SYS(0, 4, fd);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ASSERT_SYS(0, 5, send(4, "hello", 5, 0));
|
||||||
|
EXPECT_EQ(0, pthread_spin_unlock(phaser + 1));
|
||||||
|
EXPECT_SYS(0, 0, close(4));
|
||||||
|
EXPECT_SYS(0, 0, close(3));
|
||||||
|
PARENT();
|
||||||
|
EXPECT_SYS(0, 0, close(3));
|
||||||
|
ASSERT_SYS(0, 3, socket(AF_INET, SOCK_STREAM, IPPROTO_TCP));
|
||||||
|
EXPECT_EQ(0, pthread_spin_lock(phaser + 0));
|
||||||
|
ASSERT_SYS(0, 0, connect(3, (struct sockaddr *)&addr, sizeof(addr)));
|
||||||
|
EXPECT_EQ(0, pthread_spin_lock(phaser + 1));
|
||||||
|
EXPECT_SYS(0, 5, read(3, buf, 16));
|
||||||
|
EXPECT_STREQ("hello", buf);
|
||||||
|
EXPECT_SYS(0, 0, close(3));
|
||||||
|
WAIT(exit, 0);
|
||||||
|
munmap(phaser, 4096);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(O_NONBLOCK, canBeTunedWithFcntl_toMakeReadNonBlocking) {
|
||||||
|
int ws, pid;
|
||||||
|
char buf[16] = {0};
|
||||||
|
int64_t inoffset;
|
||||||
|
uint32_t addrsize = sizeof(struct sockaddr_in);
|
||||||
|
struct sockaddr_in addr = {
|
||||||
|
.sin_family = AF_INET,
|
||||||
|
.sin_addr.s_addr = htonl(0x7f000001),
|
||||||
|
};
|
||||||
|
pthread_spinlock_t *phaser = _mapshared(4096);
|
||||||
|
EXPECT_EQ(0, pthread_spin_lock(phaser + 0));
|
||||||
|
EXPECT_EQ(0, pthread_spin_lock(phaser + 1));
|
||||||
|
ASSERT_SYS(0, 3, socket(AF_INET, SOCK_STREAM, IPPROTO_TCP));
|
||||||
|
ASSERT_SYS(0, 0, bind(3, (struct sockaddr *)&addr, sizeof(addr)));
|
||||||
|
ASSERT_SYS(0, 0, getsockname(3, (struct sockaddr *)&addr, &addrsize));
|
||||||
|
ASSERT_SYS(0, 0, listen(3, SOMAXCONN));
|
||||||
|
SPAWN(fork);
|
||||||
|
ASSERT_SYS(0, 4, accept(3, (struct sockaddr *)&addr, &addrsize));
|
||||||
|
EXPECT_EQ(0, pthread_spin_lock(phaser + 0));
|
||||||
|
ASSERT_SYS(0, 5, send(4, "hello", 5, 0));
|
||||||
|
EXPECT_EQ(0, pthread_spin_lock(phaser + 1));
|
||||||
|
EXPECT_SYS(0, 0, close(4));
|
||||||
|
EXPECT_SYS(0, 0, close(3));
|
||||||
|
PARENT();
|
||||||
|
EXPECT_SYS(0, 0, close(3));
|
||||||
|
ASSERT_SYS(0, 3, socket(AF_INET, SOCK_STREAM, IPPROTO_TCP));
|
||||||
|
ASSERT_SYS(0, 0, connect(3, (struct sockaddr *)&addr, sizeof(addr)));
|
||||||
|
ASSERT_SYS(0, 0, fcntl(3, F_SETFL, O_NONBLOCK));
|
||||||
|
ASSERT_SYS(EAGAIN, -1, read(3, buf, 16));
|
||||||
|
EXPECT_EQ(0, pthread_spin_unlock(phaser + 0));
|
||||||
|
TryAgain:
|
||||||
|
int e = errno;
|
||||||
|
ssize_t rc = read(3, buf, 16);
|
||||||
|
if (rc == -1 && errno == EAGAIN) {
|
||||||
|
errno = e;
|
||||||
|
usleep(1000);
|
||||||
|
goto TryAgain;
|
||||||
|
}
|
||||||
|
EXPECT_SYS(0, 5, rc);
|
||||||
|
EXPECT_STREQ("hello", buf);
|
||||||
|
EXPECT_EQ(0, pthread_spin_unlock(phaser + 1));
|
||||||
|
EXPECT_SYS(0, 0, close(3));
|
||||||
|
WAIT(exit, 0);
|
||||||
|
munmap(phaser, 4096);
|
||||||
|
}
|
|
@ -33,6 +33,7 @@ TEST_LIBC_SOCK_DIRECTDEPS = \
|
||||||
LIBC_STDIO \
|
LIBC_STDIO \
|
||||||
LIBC_STR \
|
LIBC_STR \
|
||||||
LIBC_SYSV \
|
LIBC_SYSV \
|
||||||
|
LIBC_THREAD \
|
||||||
LIBC_LOG \
|
LIBC_LOG \
|
||||||
LIBC_SYSV_CALLS \
|
LIBC_SYSV_CALLS \
|
||||||
LIBC_TESTLIB \
|
LIBC_TESTLIB \
|
||||||
|
@ -58,6 +59,9 @@ o/$(MODE)/test/libc/sock/%.com.dbg: \
|
||||||
o/$(MODE)/test/libc/sock/unix_test.com.runs: \
|
o/$(MODE)/test/libc/sock/unix_test.com.runs: \
|
||||||
private .PLEDGE = stdio rpath wpath cpath fattr proc unix
|
private .PLEDGE = stdio rpath wpath cpath fattr proc unix
|
||||||
|
|
||||||
|
o/$(MODE)/test/libc/sock/nonblock_test.com.runs \
|
||||||
|
o/$(MODE)/test/libc/sock/socket_test.com.runs \
|
||||||
|
o/$(MODE)/test/libc/sock/shutdown_test.com.runs \
|
||||||
o/$(MODE)/test/libc/sock/setsockopt_test.com.runs \
|
o/$(MODE)/test/libc/sock/setsockopt_test.com.runs \
|
||||||
o/$(MODE)/test/libc/sock/sendfile_test.com.runs \
|
o/$(MODE)/test/libc/sock/sendfile_test.com.runs \
|
||||||
o/$(MODE)/test/libc/sock/poll_test.com.runs \
|
o/$(MODE)/test/libc/sock/poll_test.com.runs \
|
||||||
|
@ -70,17 +74,12 @@ o/$(MODE)/test/libc/sock/nointernet_test.com.runs: \
|
||||||
|
|
||||||
o/$(MODE)/test/libc/sock/socket_test.com.runs: \
|
o/$(MODE)/test/libc/sock/socket_test.com.runs: \
|
||||||
private .INTERNET = 1 # todo: ipv6 filtering
|
private .INTERNET = 1 # todo: ipv6 filtering
|
||||||
o/$(MODE)/test/libc/sock/socket_test.com.runs: \
|
|
||||||
private .PLEDGE = stdio rpath wpath cpath fattr proc inet
|
|
||||||
|
|
||||||
o/$(MODE)/test/libc/sock/recvmsg_test.com.runs: \
|
o/$(MODE)/test/libc/sock/recvmsg_test.com.runs: \
|
||||||
private .INTERNET = 1 # need to bind to 0.0.0.0
|
private .INTERNET = 1 # need to bind to 0.0.0.0
|
||||||
o/$(MODE)/test/libc/sock/recvmsg_test.com.runs: \
|
o/$(MODE)/test/libc/sock/recvmsg_test.com.runs: \
|
||||||
private .PLEDGE = stdio rpath wpath cpath fattr proc inet recvfd sendfd
|
private .PLEDGE = stdio rpath wpath cpath fattr proc inet recvfd sendfd
|
||||||
|
|
||||||
o/$(MODE)/test/libc/sock/shutdown_test.com.runs: \
|
|
||||||
private .PLEDGE = stdio rpath wpath cpath fattr proc inet
|
|
||||||
|
|
||||||
$(TEST_LIBC_SOCK_OBJS): test/libc/sock/test.mk
|
$(TEST_LIBC_SOCK_OBJS): test/libc/sock/test.mk
|
||||||
|
|
||||||
.PHONY: o/$(MODE)/test/libc/sock
|
.PHONY: o/$(MODE)/test/libc/sock
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue