From 1d4eb08fa179344df837837bcc88908380ef86e6 Mon Sep 17 00:00:00 2001 From: Justine Tunney Date: Sun, 23 Jul 2023 02:56:47 -0700 Subject: [PATCH] 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. --- libc/calls/fcntl-nt.c | 49 ++++-- libc/calls/fixupnewfd.c | 8 +- libc/calls/getdomainname.c | 2 +- libc/calls/gethostname.c | 2 +- libc/calls/ioctl.c | 46 +----- libc/calls/read-nt.c | 4 + libc/calls/readlinkat.c | 2 +- libc/calls/wincrash.c | 1 + .../accept-sysv.c => intrin/cancelioex.c} | 36 ++--- libc/intrin/intrin.mk | 2 + libc/intrin/kprintf.greg.c | 9 +- libc/{calls => intrin}/winsockerr.c | 0 libc/intrin/wsagetoverlappedresult.c | 59 ++++++++ libc/intrin/wsarecv.c | 12 +- libc/nt/kernel32/CancelIoEx.S | 4 +- libc/nt/master.sh | 4 +- libc/nt/winsock.h | 8 +- libc/nt/ws2_32/WSAGetOverlappedResult.S | 4 +- libc/runtime/inflate.c | 6 +- libc/sock/accept-nt.c | 139 ++++++++++++------ libc/sock/accept4-sysv.c | 22 ++- libc/sock/connect-nt.c | 3 +- libc/sock/fixupnewsockfd.c | 5 - libc/sock/internal.h | 36 ++--- libc/sock/recv-nt.c | 20 ++- libc/sock/recvfrom-nt.c | 17 ++- libc/sock/send-nt.c | 17 ++- libc/sock/sendfile.c | 8 +- libc/sock/sendto-nt.c | 17 ++- libc/sock/sockatmark.c | 30 +++- libc/sock/socket-nt.c | 8 - libc/sock/socket-sysv.c | 31 +--- libc/sock/syscall_fd.internal.h | 3 + libc/sock/wsablock.c | 37 ++++- libc/sysv/consts.sh | 1 - libc/sysv/consts/SIOCADDDLCI.S | 2 +- libc/sysv/consts/SIOCADDMULTI.S | 2 +- libc/sysv/consts/SIOCADDRT.S | 2 +- libc/sysv/consts/SIOCATMARK.S | 2 - libc/sysv/consts/SIOCDARP.S | 2 +- libc/sysv/consts/SIOCDELDLCI.S | 2 +- libc/sysv/consts/SIOCDELMULTI.S | 2 +- libc/sysv/consts/SIOCDELRT.S | 2 +- libc/sysv/consts/SIOCDEVPRIVATE.S | 2 +- libc/sysv/consts/SIOCDIFADDR.S | 2 +- libc/sysv/consts/SIOCDRARP.S | 2 +- libc/sysv/consts/SIOCGARP.S | 2 +- libc/sysv/consts/SIOCGIFADDR.S | 2 +- libc/sysv/consts/SIOCGIFBR.S | 2 +- libc/sysv/consts/SIOCGIFBRDADDR.S | 2 +- libc/sysv/consts/SIOCGIFCONF.S | 2 +- libc/sysv/consts/SIOCGIFCOUNT.S | 2 +- libc/sysv/consts/SIOCGIFDSTADDR.S | 2 +- libc/sysv/consts/SIOCGIFENCAP.S | 2 +- libc/sysv/consts/SIOCGIFFLAGS.S | 2 +- libc/sysv/consts/SIOCGIFHWADDR.S | 2 +- libc/sysv/consts/SIOCGIFINDEX.S | 2 +- libc/sysv/consts/SIOCGIFMAP.S | 2 +- libc/sysv/consts/SIOCGIFMEM.S | 2 +- libc/sysv/consts/SIOCGIFMETRIC.S | 2 +- libc/sysv/consts/SIOCGIFMTU.S | 2 +- libc/sysv/consts/SIOCGIFNAME.S | 2 +- libc/sysv/consts/SIOCGIFNETMASK.S | 2 +- libc/sysv/consts/SIOCGIFPFLAGS.S | 2 +- libc/sysv/consts/SIOCGIFSLAVE.S | 2 +- libc/sysv/consts/SIOCGIFTXQLEN.S | 2 +- libc/sysv/consts/SIOCGPGRP.S | 2 +- libc/sysv/consts/SIOCGRARP.S | 2 +- libc/sysv/consts/SIOCGSTAMP.S | 2 +- libc/sysv/consts/SIOCGSTAMPNS.S | 2 +- libc/sysv/consts/SIOCPROTOPRIVATE.S | 2 +- libc/sysv/consts/SIOCRTMSG.S | 2 +- libc/sysv/consts/SIOCSARP.S | 2 +- libc/sysv/consts/SIOCSIFADDR.S | 2 +- libc/sysv/consts/SIOCSIFBR.S | 2 +- libc/sysv/consts/SIOCSIFBRDADDR.S | 2 +- libc/sysv/consts/SIOCSIFDSTADDR.S | 2 +- libc/sysv/consts/SIOCSIFENCAP.S | 2 +- libc/sysv/consts/SIOCSIFFLAGS.S | 2 +- libc/sysv/consts/SIOCSIFHWADDR.S | 2 +- libc/sysv/consts/SIOCSIFHWBROADCAST.S | 2 +- libc/sysv/consts/SIOCSIFLINK.S | 2 +- libc/sysv/consts/SIOCSIFMAP.S | 2 +- libc/sysv/consts/SIOCSIFMEM.S | 2 +- libc/sysv/consts/SIOCSIFMETRIC.S | 2 +- libc/sysv/consts/SIOCSIFMTU.S | 2 +- libc/sysv/consts/SIOCSIFNAME.S | 2 +- libc/sysv/consts/SIOCSIFNETMASK.S | 2 +- libc/sysv/consts/SIOCSIFPFLAGS.S | 2 +- libc/sysv/consts/SIOCSIFSLAVE.S | 2 +- libc/sysv/consts/SIOCSIFTXQLEN.S | 2 +- libc/sysv/consts/SIOCSPGRP.S | 2 +- libc/sysv/consts/SIOCSRARP.S | 2 +- libc/sysv/consts/SIOGIFINDEX.S | 2 +- libc/sysv/consts/fio.h | 14 +- libc/sysv/consts/sio.h | 1 - libc/sysv/dos2errno.sh | 2 +- libc/thread/pthread_attr_init.c | 9 ++ test/libc/sock/nonblock_test.c | 127 ++++++++++++++++ test/libc/sock/test.mk | 9 +- third_party/python/Modules/termios.c | 18 +++ third_party/python/Python/fileutils.c | 59 ++++++-- 102 files changed, 678 insertions(+), 331 deletions(-) rename libc/{sock/accept-sysv.c => intrin/cancelioex.c} (71%) rename libc/{calls => intrin}/winsockerr.c (100%) create mode 100644 libc/intrin/wsagetoverlappedresult.c delete mode 100644 libc/sysv/consts/SIOCATMARK.S create mode 100644 test/libc/sock/nonblock_test.c diff --git a/libc/calls/fcntl-nt.c b/libc/calls/fcntl-nt.c index 197cc042f..b5dbe2aa8 100644 --- a/libc/calls/fcntl-nt.c +++ b/libc/calls/fcntl-nt.c @@ -36,10 +36,13 @@ #include "libc/nt/runtime.h" #include "libc/nt/struct/byhandlefileinformation.h" #include "libc/nt/struct/overlapped.h" +#include "libc/nt/winsock.h" +#include "libc/sock/internal.h" #include "libc/stdckdint.h" #include "libc/str/str.h" #include "libc/sysv/consts/f.h" #include "libc/sysv/consts/fd.h" +#include "libc/sysv/consts/fio.h" #include "libc/sysv/consts/o.h" #include "libc/sysv/errfuns.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); } +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) { int rc; 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 (cmd == F_GETFL) { - rc = g_fds.p[fd].flags & - (O_ACCMODE | O_APPEND | O_ASYNC | O_DIRECT | O_NOATIME | O_NONBLOCK | - O_RANDOM | O_SEQUENTIAL); + rc = g_fds.p[fd].flags & access_mode_flags; } else if (cmd == F_SETFL) { - // O_APPEND doesn't appear to be tunable at cursory glance - // 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(); + rc = sys_fcntl_nt_setfl(fd, &g_fds.p[fd].flags, arg, access_mode_flags); } else if (cmd == F_GETFD) { if (g_fds.p[fd].flags & O_CLOEXEC) { rc = FD_CLOEXEC; diff --git a/libc/calls/fixupnewfd.c b/libc/calls/fixupnewfd.c index 36f234f79..fd61c2486 100644 --- a/libc/calls/fixupnewfd.c +++ b/libc/calls/fixupnewfd.c @@ -26,9 +26,15 @@ // Applies file descriptor fixups on XNU or old Linux. // See __fixupnewsockfd() for socket file descriptors. int __fixupnewfd(int fd, int flags) { + int file_mode; if (fd != -1) { 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; diff --git a/libc/calls/getdomainname.c b/libc/calls/getdomainname.c index fb2e0cb19..885499ccb 100644 --- a/libc/calls/getdomainname.c +++ b/libc/calls/getdomainname.c @@ -76,6 +76,6 @@ int getdomainname(char *name, size_t len) { if (!rc && len && !strcmp(name, "(none)")) { 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; } diff --git a/libc/calls/gethostname.c b/libc/calls/gethostname.c index 23d91548d..0439a735f 100644 --- a/libc/calls/gethostname.c +++ b/libc/calls/gethostname.c @@ -71,6 +71,6 @@ int gethostname(char *name, size_t len) { } else { 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; } diff --git a/libc/calls/ioctl.c b/libc/calls/ioctl.c index 5e7a32beb..abc510e6a 100644 --- a/libc/calls/ioctl.c +++ b/libc/calls/ioctl.c @@ -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. * @@ -618,17 +590,6 @@ static int ioctl_fioclex(int fd, int req) { * - `TIOCNXCL` to give up exclusive mode on terminal. Only * 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, * whose arg is `struct ifconf *`. It implements the Linux style * 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 * 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() * - `TCSETS` 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); if (request == FIONBIO) { 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) { rc = tcgetwinsize(fd, arg); } else if (request == TIOCSWINSZ) { diff --git a/libc/calls/read-nt.c b/libc/calls/read-nt.c index 45fd0e5b6..d25f2c4c9 100644 --- a/libc/calls/read-nt.c +++ b/libc/calls/read-nt.c @@ -33,6 +33,7 @@ #include "libc/nt/runtime.h" #include "libc/nt/struct/overlapped.h" #include "libc/nt/synchronization.h" +#include "libc/sysv/consts/o.h" #include "libc/sysv/errfuns.h" 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) { POLLTRACE("IOCP EINTR"); } + if (fd->flags & O_NONBLOCK) { + return eagain(); + } if (_check_interrupts(true, g_fds.p)) { POLLTRACE("sys_read_nt interrupted"); return -1; diff --git a/libc/calls/readlinkat.c b/libc/calls/readlinkat.c index a6ca90120..bd8644c32 100644 --- a/libc/calls/readlinkat.c +++ b/libc/calls/readlinkat.c @@ -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); } STRACE("readlinkat(%s, %#s, [%#.*s]) → %d% m", DescribeDirfd(dirfd), path, - MAX(0, bytes), buf, bytes); + (int)MAX(0, bytes), buf, bytes); return bytes; } diff --git a/libc/calls/wincrash.c b/libc/calls/wincrash.c index 0f0d65b51..05c3f4c2d 100644 --- a/libc/calls/wincrash.c +++ b/libc/calls/wincrash.c @@ -42,6 +42,7 @@ unsigned __wincrash(struct NtExceptionPointers *ep) { ucontext_t ctx; struct CosmoTib *tib; static bool noreentry; + noreentry = true; if ((tib = __tls_enabled ? __get_tls_privileged() : 0)) { if (~tib->tib_flags & TIB_FLAG_WINCRASHING) { diff --git a/libc/sock/accept-sysv.c b/libc/intrin/cancelioex.c similarity index 71% rename from libc/sock/accept-sysv.c rename to libc/intrin/cancelioex.c index d3137f5fd..93d8c8b0f 100644 --- a/libc/sock/accept-sysv.c +++ b/libc/intrin/cancelioex.c @@ -1,7 +1,7 @@ /*-*- 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 2020 Justine Alexandra Roberts Tunney │ +│ 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 │ @@ -16,21 +16,23 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/dce.h" -#include "libc/sock/internal.h" -#include "libc/sock/struct/sockaddr.internal.h" +#include "libc/calls/syscall_support-nt.internal.h" +#include "libc/intrin/describentoverlapped.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) { - int client; - uint32_t size; - union sockaddr_storage_bsd bsd; - if (!IsBsd()) { - client = __sys_accept(server, addr, addrsize, 0); - } else { - size = sizeof(bsd); - if ((client = __sys_accept(server, &bsd, &size, 0)) != -1) { - sockaddr2linux(&bsd, size, addr, addrsize); - } - } - return client; +__msabi extern typeof(CancelIoEx) *const __imp_CancelIoEx; + +/** + * Cancels Windows i/o operation. + */ +bool32 CancelIoEx(int64_t hFile, struct NtOverlapped *opt_lpOverlapped) { + bool32 ok; + ok = __imp_CancelIoEx(hFile, opt_lpOverlapped); + if (!ok) __winerr(); + NTTRACE("CancelIoEx(%ld, %s) → %hhhd% m", hFile, + DescribeNtOverlapped(opt_lpOverlapped), ok); + return ok; } diff --git a/libc/intrin/intrin.mk b/libc/intrin/intrin.mk index 350a2b46d..da4f3b7d5 100644 --- a/libc/intrin/intrin.mk +++ b/libc/intrin/intrin.mk @@ -146,6 +146,7 @@ o/$(MODE)/libc/intrin/exit1.greg.o \ o/$(MODE)/libc/intrin/wsarecv.o \ o/$(MODE)/libc/intrin/wsarecvfrom.o \ o/$(MODE)/libc/intrin/createfile.o \ +o/$(MODE)/libc/intrin/cancelioex.o \ o/$(MODE)/libc/intrin/reopenfile.o \ o/$(MODE)/libc/intrin/deletefile.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/createfilemappingnuma.o \ o/$(MODE)/libc/intrin/waitformultipleobjects.o \ +o/$(MODE)/libc/intrin/wsagetoverlappedresult.o \ o/$(MODE)/libc/intrin/generateconsolectrlevent.o \ o/$(MODE)/libc/intrin/wsawaitformultipleevents.o: private\ CFLAGS += \ diff --git a/libc/intrin/kprintf.greg.c b/libc/intrin/kprintf.greg.c index d3598d892..275eeb6ac 100644 --- a/libc/intrin/kprintf.greg.c +++ b/libc/intrin/kprintf.greg.c @@ -26,12 +26,14 @@ #include "libc/errno.h" #include "libc/fmt/divmod10.internal.h" #include "libc/fmt/fmt.h" +#include "libc/fmt/itoa.h" #include "libc/fmt/magnumstrs.internal.h" #include "libc/intrin/asan.internal.h" #include "libc/intrin/asancodes.h" #include "libc/intrin/atomic.h" #include "libc/intrin/bits.h" #include "libc/intrin/cmpxchg.h" +#include "libc/intrin/kprintf.h" #include "libc/intrin/likely.h" #include "libc/intrin/nomultics.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) { int si, y; wint_t t, u; + char errnum[12]; const char *abet; signed char type; const char *s, *f; @@ -539,6 +542,10 @@ privileged static size_t kformat(char *b, size_t n, const char *fmt, } else { type = 0; s = _strerrno(e); + if (!s) { + FormatInt32(errnum, e); + s = errnum; + } goto FormatString; } } @@ -612,7 +619,7 @@ privileged static size_t kformat(char *b, size_t n, const char *fmt, if (cols) --cols; // end quote p = kemitquote(p, e, type, hash); } - if (sign == ' ' && (!pdot || prec) && *s) { + if (sign == ' ' && (!pdot || prec) && s && *s) { if (p < e) *p = ' '; ++p; } diff --git a/libc/calls/winsockerr.c b/libc/intrin/winsockerr.c similarity index 100% rename from libc/calls/winsockerr.c rename to libc/intrin/winsockerr.c diff --git a/libc/intrin/wsagetoverlappedresult.c b/libc/intrin/wsagetoverlappedresult.c new file mode 100644 index 000000000..dd5621352 --- /dev/null +++ b/libc/intrin/wsagetoverlappedresult.c @@ -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; +} diff --git a/libc/intrin/wsarecv.c b/libc/intrin/wsarecv.c index 45b62a596..4f52c3e61 100644 --- a/libc/intrin/wsarecv.c +++ b/libc/intrin/wsarecv.c @@ -16,6 +16,7 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/assert.h" #include "libc/calls/syscall_support-nt.internal.h" #include "libc/intrin/describeflags.internal.h" #include "libc/intrin/describentoverlapped.internal.h" @@ -23,6 +24,7 @@ #include "libc/intrin/strace.internal.h" #include "libc/nt/thunk/msabi.h" #include "libc/nt/winsock.h" +#include "libc/sock/internal.h" __msabi extern typeof(WSARecv) *const __imp_WSARecv; @@ -38,6 +40,12 @@ textwindows int WSARecv( struct NtOverlapped *opt_inout_lpOverlapped, const NtWsaOverlappedCompletionRoutine opt_lpCompletionRoutine) { 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 uint32_t NumberOfBytesRecvd; if (opt_out_lpNumberOfBytesRecvd) { @@ -50,7 +58,7 @@ textwindows int WSARecv( *opt_out_lpNumberOfBytesRecvd = NumberOfBytesRecvd; } if (rc == -1) { - __winerr(); + __winsockerr(); } if (UNLIKELY(__strace > 0) && strace_enabled(0) > 0) { kprintf(STRACE_PROLOGUE "WSARecv(%lu, [", s); @@ -66,7 +74,7 @@ textwindows int WSARecv( opt_out_lpNumberOfBytesRecvd, inout_lpFlags, opt_inout_lpOverlapped, opt_lpCompletionRoutine); if (rc == -1) { - __winerr(); + __winsockerr(); } #endif return rc; diff --git a/libc/nt/kernel32/CancelIoEx.S b/libc/nt/kernel32/CancelIoEx.S index 5dd3c3ab2..a586f6ca9 100644 --- a/libc/nt/kernel32/CancelIoEx.S +++ b/libc/nt/kernel32/CancelIoEx.S @@ -3,7 +3,7 @@ .text.windows .ftrace1 -CancelIoEx: +__CancelIoEx: .ftrace2 #ifdef __x86_64__ push %rbp @@ -14,5 +14,5 @@ CancelIoEx: mov x0,#0 ret #endif - .endfn CancelIoEx,globl + .endfn __CancelIoEx,globl .previous diff --git a/libc/nt/master.sh b/libc/nt/master.sh index 1575fd185..9b6de9275 100755 --- a/libc/nt/master.sh +++ b/libc/nt/master.sh @@ -98,7 +98,6 @@ imp 'CallNamedPipeA' CallNamedPipeA kernel32 110 7 imp 'CallbackMayRunLong' CallbackMayRunLong kernel32 0 imp 'CancelDeviceWakeupRequest' CancelDeviceWakeupRequest kernel32 113 imp 'CancelIo' CancelIo kernel32 0 1 -imp 'CancelIoEx' CancelIoEx kernel32 0 2 imp 'CancelSynchronousIo' CancelSynchronousIo kernel32 0 1 imp 'CancelTimerQueueTimer' CancelTimerQueueTimer kernel32 118 imp 'CancelWaitableTimer' CancelWaitableTimer kernel32 0 @@ -1097,6 +1096,7 @@ imp 'WriteProfileString' WriteProfileStringW kernel32 1575 imp 'WriteTapemark' WriteTapemark kernel32 1576 imp 'ZombifyActCtx' ZombifyActCtx kernel32 0 imp 'ZombifyActCtxWorker' ZombifyActCtxWorker kernel32 1578 +imp '__CancelIoEx' CancelIoEx kernel32 0 2 imp '__CloseHandle' CloseHandle kernel32 0 1 imp '__CreateDirectory' CreateDirectoryW kernel32 0 2 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 'WSAEventSelect' WSAEventSelect ws2_32 67 3 imp 'WSAGetLastError' WSAGetLastError ws2_32 111 0 -imp 'WSAGetOverlappedResult' WSAGetOverlappedResult ws2_32 68 5 imp 'WSAGetQOSByName' WSAGetQOSByName ws2_32 69 3 imp 'WSAGetServiceClassInfo' WSAGetServiceClassInfoW ws2_32 71 4 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 '__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 '__WSAGetOverlappedResult' WSAGetOverlappedResult ws2_32 68 5 # IPHLPAPI.DLL # diff --git a/libc/nt/winsock.h b/libc/nt/winsock.h index ea2273879..25e6b8a27 100644 --- a/libc/nt/winsock.h +++ b/libc/nt/winsock.h @@ -294,7 +294,7 @@ int32_t WSAStartup(uint16_t wVersionRequested, struct NtWsaData *lpWSAData) paramsnonnull() dontdiscard; int WSACleanup(void); -int WSAGetLastError(void); +int WSAGetLastError(void) nosideeffect; void WSASetLastError(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) 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, uint32_t *opt_out_lpNumberOfBytesSent, uint32_t dwFlags, struct NtOverlapped *opt_inout_lpOverlapped, diff --git a/libc/nt/ws2_32/WSAGetOverlappedResult.S b/libc/nt/ws2_32/WSAGetOverlappedResult.S index 8aea9aef0..7dbb08962 100644 --- a/libc/nt/ws2_32/WSAGetOverlappedResult.S +++ b/libc/nt/ws2_32/WSAGetOverlappedResult.S @@ -3,7 +3,7 @@ .text.windows .ftrace1 -WSAGetOverlappedResult: +__WSAGetOverlappedResult: .ftrace2 #ifdef __x86_64__ push %rbp @@ -14,5 +14,5 @@ WSAGetOverlappedResult: mov x0,#0 ret #endif - .endfn WSAGetOverlappedResult,globl + .endfn __WSAGetOverlappedResult,globl .previous diff --git a/libc/runtime/inflate.c b/libc/runtime/inflate.c index 591c09e5c..c649a0631 100644 --- a/libc/runtime/inflate.c +++ b/libc/runtime/inflate.c @@ -58,8 +58,8 @@ int __inflate(void *out, size_t outsize, const void *in, size_t insize) { } else { rc = _puff(out, &outsize, in, &insize); } - STRACE("inflate([%#.*hhs%s], %'zu, %#.*hhs%s, %'zu) → %d", MIN(40, outsize), - out, outsize > 40 ? "..." : "", outsize, MIN(40, insize), in, - insize > 40 ? "..." : "", insize, rc); + STRACE("inflate([%#.*hhs%s], %'zu, %#.*hhs%s, %'zu) → %d", + (int)MIN(40, outsize), out, outsize > 40 ? "..." : "", outsize, + (int)MIN(40, insize), in, insize > 40 ? "..." : "", insize, rc); return rc; } diff --git a/libc/sock/accept-nt.c b/libc/sock/accept-nt.c index f2087b9b5..047ff96b6 100644 --- a/libc/sock/accept-nt.c +++ b/libc/sock/accept-nt.c @@ -17,58 +17,109 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/internal.h" -#include "libc/calls/sig.internal.h" #include "libc/calls/state.internal.h" +#include "libc/macros.internal.h" #include "libc/mem/mem.h" #include "libc/nt/winsock.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/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/poll.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, - int flags) { - int64_t h; - int rc, client, oflags; - struct SockFd *sockfd, *sockfd2; - sockfd = (struct SockFd *)fd->extra; - if (_check_interrupts(true, g_fds.p)) return -1; - for (;;) { - if (!WSAPoll(&(struct sys_pollfd_nt){fd->handle, POLLIN}, 1, - __SIG_POLLING_INTERVAL_MS)) { - if (_check_interrupts(true, g_fds.p)) { - return eintr(); - } - continue; +union AcceptExAddr { + union sockaddr_storage_linux addr; + char buf[sizeof(struct sockaddr_storage) + 16]; +}; + +struct AcceptExBuffer { + union AcceptExAddr local; + union AcceptExAddr remote; +}; + +static void CopyLinuxSockAddr(const union sockaddr_storage_linux *addr, + void *out_addr, uint32_t *inout_addrsize) { + uint32_t insize, outsize; + 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) { - oflags = 0; - if (flags & SOCK_CLOEXEC) oflags |= O_CLOEXEC; - if (flags & SOCK_NONBLOCK) oflags |= O_NONBLOCK; - if ((!(flags & SOCK_NONBLOCK) || - __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(); + insize = *inout_addrsize; + if (insize) bzero(out_addr, insize); + outsize = MIN(insize, outsize); + if (outsize) memcpy(out_addr, addr, outsize); + *inout_addrsize = outsize; } } + +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; +} diff --git a/libc/sock/accept4-sysv.c b/libc/sock/accept4-sysv.c index 33d879c00..aa77bd51d 100644 --- a/libc/sock/accept4-sysv.c +++ b/libc/sock/accept4-sysv.c @@ -16,15 +16,20 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/assert.h" +#include "libc/calls/syscall-sysv.internal.h" #include "libc/dce.h" #include "libc/errno.h" #include "libc/sock/internal.h" #include "libc/sock/sock.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) { - if (!flags) return sys_accept(server, addr, addrsize); - int olderr, client; + int olderr, client, file_mode; union sockaddr_storage_bsd bsd; uint32_t size = sizeof(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; demodernize = true; TriedAndTrue: - client = __fixupnewsockfd(__sys_accept(server, out_addr, out_addrsize, 0), - flags); + if ((client = __sys_accept(server, out_addr, out_addrsize, 0)) != -1) { + // __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()) { sockaddr2linux(&bsd, size, addr, addrsize); diff --git a/libc/sock/connect-nt.c b/libc/sock/connect-nt.c index a5ee60734..63fa29a5d 100644 --- a/libc/sock/connect-nt.c +++ b/libc/sock/connect-nt.c @@ -17,6 +17,7 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/assert.h" +#include "libc/intrin/bsr.h" #include "libc/nt/winsock.h" #include "libc/sock/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; _npassert(fd->kind == kFdSocket); return __winsockblock( - fd->handle, FD_CONNECT_BIT, + fd->handle, _bsr(kNtFdConnect), WSAConnect(fd->handle, addr, addrsize, NULL, NULL, NULL, NULL), sockfd->rcvtimeo); } diff --git a/libc/sock/fixupnewsockfd.c b/libc/sock/fixupnewsockfd.c index c4116a9af..0cbeb1b95 100644 --- a/libc/sock/fixupnewsockfd.c +++ b/libc/sock/fixupnewsockfd.c @@ -21,11 +21,6 @@ #include "libc/sysv/consts/o.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) { return __fixupnewfd(fd, (((flags & SOCK_CLOEXEC) ? O_CLOEXEC : 0) | ((flags & SOCK_NONBLOCK) ? O_NONBLOCK : 0))); diff --git a/libc/sock/internal.h b/libc/sock/internal.h index 43fa01cf0..1dcdebb84 100644 --- a/libc/sock/internal.h +++ b/libc/sock/internal.h @@ -11,18 +11,16 @@ #if !(__ASSEMBLER__ + __LINKER__ + 0) COSMOPOLITAN_C_START_ -#define FD_READ (1 << FD_READ_BIT) -#define FD_READ_BIT 0 -#define FD_WRITE (1 << FD_WRITE_BIT) -#define FD_WRITE_BIT 1 -#define FD_OOB (1 << FD_OOB_BIT) -#define FD_OOB_BIT 2 -#define FD_ACCEPT (1 << FD_ACCEPT_BIT) -#define FD_ACCEPT_BIT 3 -#define FD_CONNECT (1 << FD_CONNECT_BIT) -#define FD_CONNECT_BIT 4 -#define FD_CLOSE (1 << FD_CLOSE_BIT) -#define FD_CLOSE_BIT 5 +#define kNtFdRead 1 +#define kNtFdWrite 2 +#define kNtFdOob 4 +#define kNtFdAccept 8 +#define kNtFdConnect 16 +#define kNtFdClose 32 +#define kNtFdQos 64 +#define kNtFdGroupQos 128 +#define kNtFdRoutingInterfaceChange 256 +#define kNtFdAddressListChange 512 /* ------------------------------------------------------------------------------------*/ @@ -34,17 +32,6 @@ struct SockFd { int protocol; uint32_t rcvtimeo; 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; @@ -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_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_connect(int32_t, const 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; int64_t __winsockerr(void) nocallback _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; struct SockFd *_dupsockfd(struct SockFd *) _Hide; int64_t GetNtBaseSocket(int64_t) _Hide; diff --git a/libc/sock/recv-nt.c b/libc/sock/recv-nt.c index a0f734c53..aaf83e258 100644 --- a/libc/sock/recv-nt.c +++ b/libc/sock/recv-nt.c @@ -16,9 +16,11 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/assert.h" #include "libc/calls/internal.h" #include "libc/calls/struct/fd.internal.h" #include "libc/errno.h" +#include "libc/intrin/strace.internal.h" #include "libc/nt/struct/iovec.h" #include "libc/nt/struct/overlapped.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) { int err; ssize_t rc; - uint32_t got = 0; + uint32_t got = -666; struct SockFd *sockfd; struct NtIovec iovnt[16]; - struct NtOverlapped overlapped = {.hEvent = WSACreateEvent()}; if (_check_interrupts(true, g_fds.p)) return -1; + struct NtOverlapped overlapped = {.hEvent = WSACreateEvent()}; err = errno; - if (!WSARecv(fd->handle, iovnt, __iovec2nt(iovnt, iov, iovlen), &got, &flags, - &overlapped, NULL)) { - rc = got; + if (!WSARecv(fd->handle, iovnt, __iovec2nt(iovnt, iov, iovlen), 0, &flags, + &overlapped, 0)) { + if (WSAGetOverlappedResult(fd->handle, &overlapped, &got, false, &flags)) { + rc = got; + } else { + rc = -1; + } } else { errno = err; 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; } diff --git a/libc/sock/recvfrom-nt.c b/libc/sock/recvfrom-nt.c index 1a2099db6..7726c0e4a 100644 --- a/libc/sock/recvfrom-nt.c +++ b/libc/sock/recvfrom-nt.c @@ -31,20 +31,23 @@ textwindows ssize_t sys_recvfrom_nt(struct Fd *fd, const struct iovec *iov, uint32_t *opt_inout_srcaddrsize) { int err; ssize_t rc; - uint32_t got = 0; + uint32_t got = -666; struct SockFd *sockfd; struct NtIovec iovnt[16]; - struct NtOverlapped overlapped = {.hEvent = WSACreateEvent()}; if (_check_interrupts(true, g_fds.p)) return -1; + struct NtOverlapped overlapped = {.hEvent = WSACreateEvent()}; err = errno; - if (!WSARecvFrom(fd->handle, iovnt, __iovec2nt(iovnt, iov, iovlen), &got, - &flags, opt_out_srcaddr, opt_inout_srcaddrsize, &overlapped, - NULL)) { - rc = got; + if (!WSARecvFrom(fd->handle, iovnt, __iovec2nt(iovnt, iov, iovlen), 0, &flags, + opt_out_srcaddr, opt_inout_srcaddrsize, &overlapped, NULL)) { + if (WSAGetOverlappedResult(fd->handle, &overlapped, &got, false, &flags)) { + rc = got; + } else { + rc = -1; + } } else { errno = err; 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); return rc; diff --git a/libc/sock/send-nt.c b/libc/sock/send-nt.c index 2a0f4aedf..5850daf2f 100644 --- a/libc/sock/send-nt.c +++ b/libc/sock/send-nt.c @@ -21,23 +21,28 @@ #include "libc/nt/struct/overlapped.h" #include "libc/nt/winsock.h" #include "libc/sock/internal.h" +#include "libc/sock/syscall_fd.internal.h" #include "libc/sysv/errfuns.h" textwindows ssize_t sys_send_nt(int fd, const struct iovec *iov, size_t iovlen, uint32_t flags) { ssize_t rc; - uint32_t sent = 0; + uint32_t sent = -666; struct SockFd *sockfd; struct NtIovec iovnt[16]; - struct NtOverlapped overlapped = {.hEvent = WSACreateEvent()}; 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)) { - rc = sent; + if (WSAGetOverlappedResult(g_fds.p[fd].handle, &overlapped, &sent, false, + &flags)) { + rc = sent; + } else { + rc = -1; + } } else { sockfd = (struct SockFd *)g_fds.p[fd].extra; - rc = __wsablock(g_fds.p[fd].handle, &overlapped, &flags, true, - sockfd->sndtimeo); + rc = __wsablock(g_fds.p + fd, &overlapped, &flags, true, sockfd->sndtimeo); } WSACloseEvent(overlapped.hEvent); return rc; diff --git a/libc/sock/sendfile.c b/libc/sock/sendfile.c index 53b2f8311..de45a3077 100644 --- a/libc/sock/sendfile.c +++ b/libc/sock/sendfile.c @@ -65,11 +65,11 @@ static textwindows int SendfileBlock(int64_t handle, break; } } - if (!WSAGetOverlappedResult(handle, overlapped, &got, false, &flags)) { - NTTRACE("WSAGetOverlappedResult failed %lm"); - return __winsockerr(); + if (WSAGetOverlappedResult(handle, overlapped, &got, false, &flags)) { + return got; + } else { + return -1; } - return got; } static dontinline textwindows ssize_t sys_sendfile_nt( diff --git a/libc/sock/sendto-nt.c b/libc/sock/sendto-nt.c index d870fa149..33a07cb80 100644 --- a/libc/sock/sendto-nt.c +++ b/libc/sock/sendto-nt.c @@ -21,6 +21,7 @@ #include "libc/nt/struct/overlapped.h" #include "libc/nt/winsock.h" #include "libc/sock/internal.h" +#include "libc/sock/syscall_fd.internal.h" #include "libc/sysv/errfuns.h" 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; struct SockFd *sockfd; struct NtIovec iovnt[16]; - struct NtOverlapped overlapped = {.hEvent = WSACreateEvent()}; if (_check_interrupts(true, g_fds.p)) return -1; - if (!WSASendTo(g_fds.p[fd].handle, iovnt, __iovec2nt(iovnt, iov, iovlen), - &sent, flags, opt_in_addr, in_addrsize, &overlapped, NULL)) { - rc = sent; + struct NtOverlapped overlapped = {.hEvent = WSACreateEvent()}; + if (!WSASendTo(g_fds.p[fd].handle, iovnt, __iovec2nt(iovnt, iov, iovlen), 0, + 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 { sockfd = (struct SockFd *)g_fds.p[fd].extra; - rc = __wsablock(g_fds.p[fd].handle, &overlapped, &flags, true, - sockfd->sndtimeo); + rc = __wsablock(g_fds.p + fd, &overlapped, &flags, true, sockfd->sndtimeo); } WSACloseEvent(overlapped.hEvent); return rc; diff --git a/libc/sock/sockatmark.c b/libc/sock/sockatmark.c index 24a9fedfe..2e4a30445 100644 --- a/libc/sock/sockatmark.c +++ b/libc/sock/sockatmark.c @@ -16,36 +16,50 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ 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/dce.h" #include "libc/intrin/strace.internal.h" #include "libc/nt/winsock.h" +#include "libc/sock/internal.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; + int64_t hand; uint32_t bytes; - if (WSAIoctl(fd, SIOCATMARK, 0, 0, &res, sizeof(res), &bytes, 0, 0) != -1) { - return !res; - } else { - return -1; + if (fd >= g_fds.n) return ebadf(); + if (g_fds.p[fd].kind != kFdSocket) return einval(); + hand = g_fds.p[fd].handle; + 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. * * @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 rc; + unsigned long magnum; + if (IsLinux()) { + magnum = 0x8905; // SIOCATMARK (Linux only) + } else { // + magnum = 0x40047307; // SIOCATMARK (BSD, Windows) + } if (!IsWindows()) { - if (sys_ioctl(fd, SIOCATMARK, &rc) == -1) { + if (sys_ioctl(fd, magnum, &rc) == -1) { rc = -1; } } else { - rc = sockatmark_nt(fd); + rc = sockatmark_nt(fd, magnum); } STRACE("sockatmark(%d) → %d% m", fd, rc); return rc; diff --git a/libc/sock/socket-nt.c b/libc/sock/socket-nt.c index 335e62d6b..5e9874b1a 100644 --- a/libc/sock/socket-nt.c +++ b/libc/sock/socket-nt.c @@ -24,7 +24,6 @@ #include "libc/nt/winsock.h" #include "libc/sock/internal.h" #include "libc/sock/yoink.inc" -#include "libc/sysv/consts/fio.h" #include "libc/sysv/consts/ipproto.h" #include "libc/sysv/consts/o.h" #include "libc/sysv/consts/so.h" @@ -52,13 +51,6 @@ textwindows int sys_socket_nt(int family, int type, int protocol) { oflags = 0; if (type & SOCK_CLOEXEC) oflags |= O_CLOEXEC; 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->family = family; sockfd->type = truetype; diff --git a/libc/sock/socket-sysv.c b/libc/sock/socket-sysv.c index e11e42bcf..899a408ed 100644 --- a/libc/sock/socket-sysv.c +++ b/libc/sock/socket-sysv.c @@ -22,29 +22,12 @@ #include "libc/sysv/consts/sock.h" int sys_socket(int family, int type, int protocol) { - static bool once, demodernize; - int sock, olderr; - if (!once && (type & (SOCK_CLOEXEC | SOCK_NONBLOCK))) { - if (IsXnu()) { - demodernize = true; - once = true; - } 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); + int sock, tf, e = errno; + tf = SOCK_CLOEXEC | SOCK_NONBLOCK; + sock = __sys_socket(family, type, protocol); + if (sock == -1 && (type & tf) && (errno == EINVAL || errno == EPROTOTYPE)) { + errno = e; // XNU/RHEL5/etc. don't support flags; see if removing helps + sock = __fixupnewsockfd(__sys_socket(family, type & ~tf, protocol), type); } + return sock; } diff --git a/libc/sock/syscall_fd.internal.h b/libc/sock/syscall_fd.internal.h index 7604ca17b..e305185d6 100644 --- a/libc/sock/syscall_fd.internal.h +++ b/libc/sock/syscall_fd.internal.h @@ -2,6 +2,7 @@ #define COSMOPOLITAN_LIBC_SOCK_SYSCALL_INTERNAL_H_ #include "libc/calls/struct/fd.internal.h" #include "libc/calls/struct/iovec.h" +#include "libc/nt/struct/overlapped.h" #if !(__ASSEMBLER__ + __LINKER__ + 0) 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_recvfrom_nt(struct Fd *, const struct iovec *, size_t, uint32_t, void *, uint32_t *) _Hide; +int __wsablock(struct Fd *, struct NtOverlapped *, uint32_t *, bool, + uint32_t) _Hide; COSMOPOLITAN_C_END_ #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ diff --git a/libc/sock/wsablock.c b/libc/sock/wsablock.c index a7669eb03..c66978712 100644 --- a/libc/sock/wsablock.c +++ b/libc/sock/wsablock.c @@ -16,24 +16,41 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/assert.h" #include "libc/calls/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/nt/enum/wait.h" +#include "libc/nt/enum/wsa.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/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" -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 timeout) { - int rc; - uint32_t i, got; + int e, rc; + uint32_t i, got = -666; if (WSAGetLastError() != kNtErrorIoPending) { - NTTRACE("sock i/o failed %lm"); + NTTRACE("sock i/o failed %s", strerror(errno)); return __winsockerr(); } + if (fd->flags & O_NONBLOCK) { + e = errno; + _unassert(CancelIoEx(fd->handle, overlapped) || + WSAGetLastError() == kNtErrorNotFound); + errno = e; + } for (;;) { i = WSAWaitForMultipleEvents(1, &overlapped->hEvent, true, __SIG_POLLING_INTERVAL_MS, true); @@ -46,6 +63,7 @@ textwindows int __wsablock(int64_t handle, struct NtOverlapped *overlapped, } if (timeout) { if (timeout <= __SIG_POLLING_INTERVAL_MS) { + NTTRACE("__wsablock timeout elapsed"); return eagain(); } timeout -= __SIG_POLLING_INTERVAL_MS; @@ -54,9 +72,12 @@ textwindows int __wsablock(int64_t handle, struct NtOverlapped *overlapped, break; } } - if (!WSAGetOverlappedResult(handle, overlapped, &got, false, flags)) { - NTTRACE("WSAGetOverlappedResult failed %lm"); - return __winsockerr(); + if (WSAGetOverlappedResult(fd->handle, overlapped, &got, false, flags)) { + return got; + } else if ((fd->flags & O_NONBLOCK) && + WSAGetLastError() == kNtErrorOperationAborted) { + return eagain(); + } else { + return -1; } - return got; } diff --git a/libc/sysv/consts.sh b/libc/sysv/consts.sh index 9475952db..3656a24a7 100755 --- a/libc/sysv/consts.sh +++ b/libc/sysv/consts.sh @@ -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 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 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 SIOCDELMULTI 0x8932 0x8932 0x80206932 0x80206932 0x80206932 0x80206932 0x80206932 0 # bsd consensus syscon ioctl SIOCDIFADDR 0x8936 0x8936 0x80206919 0x80206919 0x80206919 0x80206919 0x80206919 0 # bsd consensus diff --git a/libc/sysv/consts/SIOCADDDLCI.S b/libc/sysv/consts/SIOCADDDLCI.S index c7fb754ba..126ec517f 100644 --- a/libc/sysv/consts/SIOCADDDLCI.S +++ b/libc/sysv/consts/SIOCADDDLCI.S @@ -1,2 +1,2 @@ #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 diff --git a/libc/sysv/consts/SIOCADDMULTI.S b/libc/sysv/consts/SIOCADDMULTI.S index e07fe2b0f..6c51f8f2b 100644 --- a/libc/sysv/consts/SIOCADDMULTI.S +++ b/libc/sysv/consts/SIOCADDMULTI.S @@ -1,2 +1,2 @@ #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 diff --git a/libc/sysv/consts/SIOCADDRT.S b/libc/sysv/consts/SIOCADDRT.S index e8ed0e6ba..a736836c7 100644 --- a/libc/sysv/consts/SIOCADDRT.S +++ b/libc/sysv/consts/SIOCADDRT.S @@ -1,2 +1,2 @@ #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 diff --git a/libc/sysv/consts/SIOCATMARK.S b/libc/sysv/consts/SIOCATMARK.S deleted file mode 100644 index fb4ab9df9..000000000 --- a/libc/sysv/consts/SIOCATMARK.S +++ /dev/null @@ -1,2 +0,0 @@ -#include "libc/sysv/consts/syscon.internal.h" -.syscon sio,SIOCATMARK,0x8905,0x8905,0x40047307,0x40047307,0x40047307,0x40047307,0x40047307,0x40047307 diff --git a/libc/sysv/consts/SIOCDARP.S b/libc/sysv/consts/SIOCDARP.S index 6ff29d49c..b3f4ee966 100644 --- a/libc/sysv/consts/SIOCDARP.S +++ b/libc/sysv/consts/SIOCDARP.S @@ -1,2 +1,2 @@ #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 diff --git a/libc/sysv/consts/SIOCDELDLCI.S b/libc/sysv/consts/SIOCDELDLCI.S index 17a100303..dc0a19cfc 100644 --- a/libc/sysv/consts/SIOCDELDLCI.S +++ b/libc/sysv/consts/SIOCDELDLCI.S @@ -1,2 +1,2 @@ #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 diff --git a/libc/sysv/consts/SIOCDELMULTI.S b/libc/sysv/consts/SIOCDELMULTI.S index 4d5687597..60627d042 100644 --- a/libc/sysv/consts/SIOCDELMULTI.S +++ b/libc/sysv/consts/SIOCDELMULTI.S @@ -1,2 +1,2 @@ #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 diff --git a/libc/sysv/consts/SIOCDELRT.S b/libc/sysv/consts/SIOCDELRT.S index fc74a0114..50d546820 100644 --- a/libc/sysv/consts/SIOCDELRT.S +++ b/libc/sysv/consts/SIOCDELRT.S @@ -1,2 +1,2 @@ #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 diff --git a/libc/sysv/consts/SIOCDEVPRIVATE.S b/libc/sysv/consts/SIOCDEVPRIVATE.S index 25b89ee1d..2a2dbb227 100644 --- a/libc/sysv/consts/SIOCDEVPRIVATE.S +++ b/libc/sysv/consts/SIOCDEVPRIVATE.S @@ -1,2 +1,2 @@ #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 diff --git a/libc/sysv/consts/SIOCDIFADDR.S b/libc/sysv/consts/SIOCDIFADDR.S index 1e1993210..aa60ea9dc 100644 --- a/libc/sysv/consts/SIOCDIFADDR.S +++ b/libc/sysv/consts/SIOCDIFADDR.S @@ -1,2 +1,2 @@ #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 diff --git a/libc/sysv/consts/SIOCDRARP.S b/libc/sysv/consts/SIOCDRARP.S index 4afc68dfd..7224ae2ac 100644 --- a/libc/sysv/consts/SIOCDRARP.S +++ b/libc/sysv/consts/SIOCDRARP.S @@ -1,2 +1,2 @@ #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 diff --git a/libc/sysv/consts/SIOCGARP.S b/libc/sysv/consts/SIOCGARP.S index 4d022aa3b..684099f5b 100644 --- a/libc/sysv/consts/SIOCGARP.S +++ b/libc/sysv/consts/SIOCGARP.S @@ -1,2 +1,2 @@ #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 diff --git a/libc/sysv/consts/SIOCGIFADDR.S b/libc/sysv/consts/SIOCGIFADDR.S index a4247ca13..ba2a126bf 100644 --- a/libc/sysv/consts/SIOCGIFADDR.S +++ b/libc/sysv/consts/SIOCGIFADDR.S @@ -1,2 +1,2 @@ #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 diff --git a/libc/sysv/consts/SIOCGIFBR.S b/libc/sysv/consts/SIOCGIFBR.S index a11138e05..9395f70a4 100644 --- a/libc/sysv/consts/SIOCGIFBR.S +++ b/libc/sysv/consts/SIOCGIFBR.S @@ -1,2 +1,2 @@ #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 diff --git a/libc/sysv/consts/SIOCGIFBRDADDR.S b/libc/sysv/consts/SIOCGIFBRDADDR.S index 34fda6435..8953533d5 100644 --- a/libc/sysv/consts/SIOCGIFBRDADDR.S +++ b/libc/sysv/consts/SIOCGIFBRDADDR.S @@ -1,2 +1,2 @@ #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 diff --git a/libc/sysv/consts/SIOCGIFCONF.S b/libc/sysv/consts/SIOCGIFCONF.S index 260ba6c03..f68ebd8fb 100644 --- a/libc/sysv/consts/SIOCGIFCONF.S +++ b/libc/sysv/consts/SIOCGIFCONF.S @@ -1,2 +1,2 @@ #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 diff --git a/libc/sysv/consts/SIOCGIFCOUNT.S b/libc/sysv/consts/SIOCGIFCOUNT.S index 25214a35a..070eae21a 100644 --- a/libc/sysv/consts/SIOCGIFCOUNT.S +++ b/libc/sysv/consts/SIOCGIFCOUNT.S @@ -1,2 +1,2 @@ #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 diff --git a/libc/sysv/consts/SIOCGIFDSTADDR.S b/libc/sysv/consts/SIOCGIFDSTADDR.S index 28e9894af..6f9adb3b8 100644 --- a/libc/sysv/consts/SIOCGIFDSTADDR.S +++ b/libc/sysv/consts/SIOCGIFDSTADDR.S @@ -1,2 +1,2 @@ #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 diff --git a/libc/sysv/consts/SIOCGIFENCAP.S b/libc/sysv/consts/SIOCGIFENCAP.S index 9a8ef28bc..c881dcfc5 100644 --- a/libc/sysv/consts/SIOCGIFENCAP.S +++ b/libc/sysv/consts/SIOCGIFENCAP.S @@ -1,2 +1,2 @@ #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 diff --git a/libc/sysv/consts/SIOCGIFFLAGS.S b/libc/sysv/consts/SIOCGIFFLAGS.S index 5a55873f5..ed94c6968 100644 --- a/libc/sysv/consts/SIOCGIFFLAGS.S +++ b/libc/sysv/consts/SIOCGIFFLAGS.S @@ -1,2 +1,2 @@ #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 diff --git a/libc/sysv/consts/SIOCGIFHWADDR.S b/libc/sysv/consts/SIOCGIFHWADDR.S index ed8414d3b..3eae39879 100644 --- a/libc/sysv/consts/SIOCGIFHWADDR.S +++ b/libc/sysv/consts/SIOCGIFHWADDR.S @@ -1,2 +1,2 @@ #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 diff --git a/libc/sysv/consts/SIOCGIFINDEX.S b/libc/sysv/consts/SIOCGIFINDEX.S index 539072b16..63ebb7dc9 100644 --- a/libc/sysv/consts/SIOCGIFINDEX.S +++ b/libc/sysv/consts/SIOCGIFINDEX.S @@ -1,2 +1,2 @@ #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 diff --git a/libc/sysv/consts/SIOCGIFMAP.S b/libc/sysv/consts/SIOCGIFMAP.S index a1767aca6..a244e9385 100644 --- a/libc/sysv/consts/SIOCGIFMAP.S +++ b/libc/sysv/consts/SIOCGIFMAP.S @@ -1,2 +1,2 @@ #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 diff --git a/libc/sysv/consts/SIOCGIFMEM.S b/libc/sysv/consts/SIOCGIFMEM.S index e138cd998..95c2feaa1 100644 --- a/libc/sysv/consts/SIOCGIFMEM.S +++ b/libc/sysv/consts/SIOCGIFMEM.S @@ -1,2 +1,2 @@ #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 diff --git a/libc/sysv/consts/SIOCGIFMETRIC.S b/libc/sysv/consts/SIOCGIFMETRIC.S index a45fb2804..432c77c56 100644 --- a/libc/sysv/consts/SIOCGIFMETRIC.S +++ b/libc/sysv/consts/SIOCGIFMETRIC.S @@ -1,2 +1,2 @@ #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 diff --git a/libc/sysv/consts/SIOCGIFMTU.S b/libc/sysv/consts/SIOCGIFMTU.S index 5548e271d..7eb0ea5be 100644 --- a/libc/sysv/consts/SIOCGIFMTU.S +++ b/libc/sysv/consts/SIOCGIFMTU.S @@ -1,2 +1,2 @@ #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 diff --git a/libc/sysv/consts/SIOCGIFNAME.S b/libc/sysv/consts/SIOCGIFNAME.S index e2513434e..b24be3869 100644 --- a/libc/sysv/consts/SIOCGIFNAME.S +++ b/libc/sysv/consts/SIOCGIFNAME.S @@ -1,2 +1,2 @@ #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 diff --git a/libc/sysv/consts/SIOCGIFNETMASK.S b/libc/sysv/consts/SIOCGIFNETMASK.S index 0c2651204..b7641227e 100644 --- a/libc/sysv/consts/SIOCGIFNETMASK.S +++ b/libc/sysv/consts/SIOCGIFNETMASK.S @@ -1,2 +1,2 @@ #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 diff --git a/libc/sysv/consts/SIOCGIFPFLAGS.S b/libc/sysv/consts/SIOCGIFPFLAGS.S index f245a5f37..75dca5697 100644 --- a/libc/sysv/consts/SIOCGIFPFLAGS.S +++ b/libc/sysv/consts/SIOCGIFPFLAGS.S @@ -1,2 +1,2 @@ #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 diff --git a/libc/sysv/consts/SIOCGIFSLAVE.S b/libc/sysv/consts/SIOCGIFSLAVE.S index 99e056f03..293b1afb0 100644 --- a/libc/sysv/consts/SIOCGIFSLAVE.S +++ b/libc/sysv/consts/SIOCGIFSLAVE.S @@ -1,2 +1,2 @@ #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 diff --git a/libc/sysv/consts/SIOCGIFTXQLEN.S b/libc/sysv/consts/SIOCGIFTXQLEN.S index 4baea20fd..342b317a0 100644 --- a/libc/sysv/consts/SIOCGIFTXQLEN.S +++ b/libc/sysv/consts/SIOCGIFTXQLEN.S @@ -1,2 +1,2 @@ #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 diff --git a/libc/sysv/consts/SIOCGPGRP.S b/libc/sysv/consts/SIOCGPGRP.S index 5785d6826..a4b369f12 100644 --- a/libc/sysv/consts/SIOCGPGRP.S +++ b/libc/sysv/consts/SIOCGPGRP.S @@ -1,2 +1,2 @@ #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 diff --git a/libc/sysv/consts/SIOCGRARP.S b/libc/sysv/consts/SIOCGRARP.S index 841f9fac6..88787f77a 100644 --- a/libc/sysv/consts/SIOCGRARP.S +++ b/libc/sysv/consts/SIOCGRARP.S @@ -1,2 +1,2 @@ #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 diff --git a/libc/sysv/consts/SIOCGSTAMP.S b/libc/sysv/consts/SIOCGSTAMP.S index 92b9ad4a3..a8b72650f 100644 --- a/libc/sysv/consts/SIOCGSTAMP.S +++ b/libc/sysv/consts/SIOCGSTAMP.S @@ -1,2 +1,2 @@ #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 diff --git a/libc/sysv/consts/SIOCGSTAMPNS.S b/libc/sysv/consts/SIOCGSTAMPNS.S index 62b7e8f34..47496f0ed 100644 --- a/libc/sysv/consts/SIOCGSTAMPNS.S +++ b/libc/sysv/consts/SIOCGSTAMPNS.S @@ -1,2 +1,2 @@ #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 diff --git a/libc/sysv/consts/SIOCPROTOPRIVATE.S b/libc/sysv/consts/SIOCPROTOPRIVATE.S index aa667f477..0bbccde4f 100644 --- a/libc/sysv/consts/SIOCPROTOPRIVATE.S +++ b/libc/sysv/consts/SIOCPROTOPRIVATE.S @@ -1,2 +1,2 @@ #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 diff --git a/libc/sysv/consts/SIOCRTMSG.S b/libc/sysv/consts/SIOCRTMSG.S index c11cef44c..a7a9f83da 100644 --- a/libc/sysv/consts/SIOCRTMSG.S +++ b/libc/sysv/consts/SIOCRTMSG.S @@ -1,2 +1,2 @@ #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 diff --git a/libc/sysv/consts/SIOCSARP.S b/libc/sysv/consts/SIOCSARP.S index 0e4a23065..87b100637 100644 --- a/libc/sysv/consts/SIOCSARP.S +++ b/libc/sysv/consts/SIOCSARP.S @@ -1,2 +1,2 @@ #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 diff --git a/libc/sysv/consts/SIOCSIFADDR.S b/libc/sysv/consts/SIOCSIFADDR.S index e62b781cc..9255ceb95 100644 --- a/libc/sysv/consts/SIOCSIFADDR.S +++ b/libc/sysv/consts/SIOCSIFADDR.S @@ -1,2 +1,2 @@ #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 diff --git a/libc/sysv/consts/SIOCSIFBR.S b/libc/sysv/consts/SIOCSIFBR.S index f43ae83a0..711d3fee5 100644 --- a/libc/sysv/consts/SIOCSIFBR.S +++ b/libc/sysv/consts/SIOCSIFBR.S @@ -1,2 +1,2 @@ #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 diff --git a/libc/sysv/consts/SIOCSIFBRDADDR.S b/libc/sysv/consts/SIOCSIFBRDADDR.S index ace55632c..8a5d5cbe7 100644 --- a/libc/sysv/consts/SIOCSIFBRDADDR.S +++ b/libc/sysv/consts/SIOCSIFBRDADDR.S @@ -1,2 +1,2 @@ #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 diff --git a/libc/sysv/consts/SIOCSIFDSTADDR.S b/libc/sysv/consts/SIOCSIFDSTADDR.S index 104c5d04d..dcd1a9132 100644 --- a/libc/sysv/consts/SIOCSIFDSTADDR.S +++ b/libc/sysv/consts/SIOCSIFDSTADDR.S @@ -1,2 +1,2 @@ #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 diff --git a/libc/sysv/consts/SIOCSIFENCAP.S b/libc/sysv/consts/SIOCSIFENCAP.S index 13b384bfd..936032fce 100644 --- a/libc/sysv/consts/SIOCSIFENCAP.S +++ b/libc/sysv/consts/SIOCSIFENCAP.S @@ -1,2 +1,2 @@ #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 diff --git a/libc/sysv/consts/SIOCSIFFLAGS.S b/libc/sysv/consts/SIOCSIFFLAGS.S index ff6475a4a..ab1d14e05 100644 --- a/libc/sysv/consts/SIOCSIFFLAGS.S +++ b/libc/sysv/consts/SIOCSIFFLAGS.S @@ -1,2 +1,2 @@ #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 diff --git a/libc/sysv/consts/SIOCSIFHWADDR.S b/libc/sysv/consts/SIOCSIFHWADDR.S index b30ee6b3c..6c111ba64 100644 --- a/libc/sysv/consts/SIOCSIFHWADDR.S +++ b/libc/sysv/consts/SIOCSIFHWADDR.S @@ -1,2 +1,2 @@ #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 diff --git a/libc/sysv/consts/SIOCSIFHWBROADCAST.S b/libc/sysv/consts/SIOCSIFHWBROADCAST.S index f154ac56c..d993ca2c7 100644 --- a/libc/sysv/consts/SIOCSIFHWBROADCAST.S +++ b/libc/sysv/consts/SIOCSIFHWBROADCAST.S @@ -1,2 +1,2 @@ #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 diff --git a/libc/sysv/consts/SIOCSIFLINK.S b/libc/sysv/consts/SIOCSIFLINK.S index 1f9293891..44c14f13d 100644 --- a/libc/sysv/consts/SIOCSIFLINK.S +++ b/libc/sysv/consts/SIOCSIFLINK.S @@ -1,2 +1,2 @@ #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 diff --git a/libc/sysv/consts/SIOCSIFMAP.S b/libc/sysv/consts/SIOCSIFMAP.S index b4d27b39b..8d498a969 100644 --- a/libc/sysv/consts/SIOCSIFMAP.S +++ b/libc/sysv/consts/SIOCSIFMAP.S @@ -1,2 +1,2 @@ #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 diff --git a/libc/sysv/consts/SIOCSIFMEM.S b/libc/sysv/consts/SIOCSIFMEM.S index a116cdb24..e03d16b75 100644 --- a/libc/sysv/consts/SIOCSIFMEM.S +++ b/libc/sysv/consts/SIOCSIFMEM.S @@ -1,2 +1,2 @@ #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 diff --git a/libc/sysv/consts/SIOCSIFMETRIC.S b/libc/sysv/consts/SIOCSIFMETRIC.S index b7c4d6b40..b521aaa49 100644 --- a/libc/sysv/consts/SIOCSIFMETRIC.S +++ b/libc/sysv/consts/SIOCSIFMETRIC.S @@ -1,2 +1,2 @@ #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 diff --git a/libc/sysv/consts/SIOCSIFMTU.S b/libc/sysv/consts/SIOCSIFMTU.S index ad9a6719f..4e71f7879 100644 --- a/libc/sysv/consts/SIOCSIFMTU.S +++ b/libc/sysv/consts/SIOCSIFMTU.S @@ -1,2 +1,2 @@ #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 diff --git a/libc/sysv/consts/SIOCSIFNAME.S b/libc/sysv/consts/SIOCSIFNAME.S index b78e8e8f7..ae3ae91e6 100644 --- a/libc/sysv/consts/SIOCSIFNAME.S +++ b/libc/sysv/consts/SIOCSIFNAME.S @@ -1,2 +1,2 @@ #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 diff --git a/libc/sysv/consts/SIOCSIFNETMASK.S b/libc/sysv/consts/SIOCSIFNETMASK.S index 023bc79cc..edfe3286e 100644 --- a/libc/sysv/consts/SIOCSIFNETMASK.S +++ b/libc/sysv/consts/SIOCSIFNETMASK.S @@ -1,2 +1,2 @@ #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 diff --git a/libc/sysv/consts/SIOCSIFPFLAGS.S b/libc/sysv/consts/SIOCSIFPFLAGS.S index 75b0d6b8a..1bc1b95b7 100644 --- a/libc/sysv/consts/SIOCSIFPFLAGS.S +++ b/libc/sysv/consts/SIOCSIFPFLAGS.S @@ -1,2 +1,2 @@ #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 diff --git a/libc/sysv/consts/SIOCSIFSLAVE.S b/libc/sysv/consts/SIOCSIFSLAVE.S index d496727ae..f71c4fe4c 100644 --- a/libc/sysv/consts/SIOCSIFSLAVE.S +++ b/libc/sysv/consts/SIOCSIFSLAVE.S @@ -1,2 +1,2 @@ #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 diff --git a/libc/sysv/consts/SIOCSIFTXQLEN.S b/libc/sysv/consts/SIOCSIFTXQLEN.S index 2d5f2afe6..477f1c391 100644 --- a/libc/sysv/consts/SIOCSIFTXQLEN.S +++ b/libc/sysv/consts/SIOCSIFTXQLEN.S @@ -1,2 +1,2 @@ #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 diff --git a/libc/sysv/consts/SIOCSPGRP.S b/libc/sysv/consts/SIOCSPGRP.S index dbb7dbdce..41e79fa94 100644 --- a/libc/sysv/consts/SIOCSPGRP.S +++ b/libc/sysv/consts/SIOCSPGRP.S @@ -1,2 +1,2 @@ #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 diff --git a/libc/sysv/consts/SIOCSRARP.S b/libc/sysv/consts/SIOCSRARP.S index f5f42af8f..10fe7ce4b 100644 --- a/libc/sysv/consts/SIOCSRARP.S +++ b/libc/sysv/consts/SIOCSRARP.S @@ -1,2 +1,2 @@ #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 diff --git a/libc/sysv/consts/SIOGIFINDEX.S b/libc/sysv/consts/SIOGIFINDEX.S index 63795f061..daa161df1 100644 --- a/libc/sysv/consts/SIOGIFINDEX.S +++ b/libc/sysv/consts/SIOGIFINDEX.S @@ -1,2 +1,2 @@ #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 diff --git a/libc/sysv/consts/fio.h b/libc/sysv/consts/fio.h index 518ceb71f..b34d6694e 100644 --- a/libc/sysv/consts/fio.h +++ b/libc/sysv/consts/fio.h @@ -3,16 +3,12 @@ #if !(__ASSEMBLER__ + __LINKER__ + 0) COSMOPOLITAN_C_START_ -extern const uint32_t FIOASYNC; -extern const uint32_t FIOCLEX; -extern const uint32_t FIONBIO; -extern const uint32_t FIONCLEX; -extern const uint32_t FIONREAD; +extern const uint32_t FIONREAD; /* one of the few encouraged ioctls */ +extern const uint32_t FIONBIO; /* use fcntl(fd, F_SETFL, O_NONBLOCK) */ +extern const uint32_t FIOCLEX; /* use fcntl(fd, F_SETFD, FD_CLOEXEC) */ +extern const uint32_t FIONCLEX; /* use fcntl(fd, F_SETFD, 0) */ +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 COSMOPOLITAN_C_END_ diff --git a/libc/sysv/consts/sio.h b/libc/sysv/consts/sio.h index e5c10b84a..bbb713ba8 100644 --- a/libc/sysv/consts/sio.h +++ b/libc/sysv/consts/sio.h @@ -6,7 +6,6 @@ COSMOPOLITAN_C_START_ extern const unsigned long SIOCADDDLCI; extern const unsigned long SIOCADDMULTI; extern const unsigned long SIOCADDRT; -extern const unsigned long SIOCATMARK; /* use sockatmark() */ extern const unsigned long SIOCDARP; extern const unsigned long SIOCDELDLCI; extern const unsigned long SIOCDELMULTI; diff --git a/libc/sysv/dos2errno.sh b/libc/sysv/dos2errno.sh index ba5d2ec01..36240fcac 100755 --- a/libc/sysv/dos2errno.sh +++ b/libc/sysv/dos2errno.sh @@ -55,7 +55,7 @@ dos kNtErrorInvalidFunction EINVAL dos kNtErrorNegativeSeek EINVAL dos kNtErrorInvalidNetname EADDRNOTAVAIL dos kNtErrorInvalidUserBuffer EMSGSIZE -dos kNtErrorIoPending EINPROGRESS +dos kNtErrorIoPending EINPROGRESS dos kNtErrorLockViolation EAGAIN dos kNtErrorMoreData EMSGSIZE dos kNtErrorNetnameDeleted ECONNABORTED diff --git a/libc/thread/pthread_attr_init.c b/libc/thread/pthread_attr_init.c index 111f6ca4e..87b7f7441 100644 --- a/libc/thread/pthread_attr_init.c +++ b/libc/thread/pthread_attr_init.c @@ -23,6 +23,15 @@ * Initializes pthread attributes. * * @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) { *attr = (pthread_attr_t){ diff --git a/test/libc/sock/nonblock_test.c b/test/libc/sock/nonblock_test.c new file mode 100644 index 000000000..ef6abb55e --- /dev/null +++ b/test/libc/sock/nonblock_test.c @@ -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); +} diff --git a/test/libc/sock/test.mk b/test/libc/sock/test.mk index b9f514b36..c970b882a 100644 --- a/test/libc/sock/test.mk +++ b/test/libc/sock/test.mk @@ -33,6 +33,7 @@ TEST_LIBC_SOCK_DIRECTDEPS = \ LIBC_STDIO \ LIBC_STR \ LIBC_SYSV \ + LIBC_THREAD \ LIBC_LOG \ LIBC_SYSV_CALLS \ LIBC_TESTLIB \ @@ -58,6 +59,9 @@ o/$(MODE)/test/libc/sock/%.com.dbg: \ o/$(MODE)/test/libc/sock/unix_test.com.runs: \ 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/sendfile_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: \ 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: \ private .INTERNET = 1 # need to bind to 0.0.0.0 o/$(MODE)/test/libc/sock/recvmsg_test.com.runs: \ 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 .PHONY: o/$(MODE)/test/libc/sock diff --git a/third_party/python/Modules/termios.c b/third_party/python/Modules/termios.c index 11f4efcf8..31baad8ce 100644 --- a/third_party/python/Modules/termios.c +++ b/third_party/python/Modules/termios.c @@ -684,11 +684,21 @@ PyInit_termios(void) PyModule_AddIntConstant(m, "CWERASE", CWERASE); /* ioctl */ +#ifdef FIOCLEX PyModule_AddIntConstant(m, "FIOCLEX", FIOCLEX); +#endif +#ifdef FIONCLEX PyModule_AddIntConstant(m, "FIONCLEX", FIONCLEX); +#endif +#ifdef FIONBIO PyModule_AddIntConstant(m, "FIONBIO", FIONBIO); +#endif +#ifdef FIONREAD PyModule_AddIntConstant(m, "FIONREAD", FIONREAD); +#endif +#ifdef FIOASYNC PyModule_AddIntConstant(m, "FIOASYNC", FIOASYNC); +#endif if (EXTA) PyModule_AddIntConstant(m, "EXTA", EXTA); if (EXTB) PyModule_AddIntConstant(m, "EXTB", EXTB); @@ -744,17 +754,25 @@ PyInit_termios(void) /* TODO(jart): NOSTOP */ /* TODO(jart): START */ /* TODO(jart): STOP */ +#ifdef TIOCSCTTY if (TIOCSCTTY) PyModule_AddIntConstant(m, "TIOCSCTTY", TIOCSCTTY); +#endif /* TODO(jart): TIOCSERCONFIG */ /* TODO(jart): TIOCSERGSTRUCT */ /* TODO(jart): TIOCSERGWILD */ /* TODO(jart): TIOCSERSWILD */ +#ifdef TIOCSETD if (TIOCSETD) PyModule_AddIntConstant(m, "TIOCSETD", TIOCSETD); +#endif /* TODO(jart): TIOCSLCKTRMIOS */ +#ifdef TIOCSPGRP if (TIOCSPGRP) PyModule_AddIntConstant(m, "TIOCSPGRP", TIOCSPGRP); +#endif /* TODO(jart): TIOCSSERIAL */ /* TODO(jart): TIOCSSOFTCAR */ +#ifdef TIOCSTI if (TIOCSTI) PyModule_AddIntConstant(m, "TIOCSTI", TIOCSTI); +#endif /* TODO(jart): TIOCTTYGSTRUCT */ return m; diff --git a/third_party/python/Python/fileutils.c b/third_party/python/Python/fileutils.c index 04d3e8824..73534591b 100644 --- a/third_party/python/Python/fileutils.c +++ b/third_party/python/Python/fileutils.c @@ -446,8 +446,18 @@ _Py_get_inheritable(int fd) static int set_inheritable(int fd, int inheritable, int raise, int *atomic_flag_works) { +#ifdef MS_WINDOWS + HANDLE handle; + DWORD flags; +#else +#if defined(HAVE_SYS_IOCTL_H) && defined(FIOCLEX) && defined(FIONCLEX) static int ioctl_works = -1; - int res, err, flags, new_flags; + int request; + int err; +#endif + int flags, new_flags; + int res; +#endif /* atomic_flag_works can only be used to make the file descriptor non-inheritable */ @@ -460,22 +470,49 @@ set_inheritable(int fd, int inheritable, int raise, int *atomic_flag_works) return -1; *atomic_flag_works = !isInheritable; } + if (*atomic_flag_works) return 0; } +#ifdef MS_WINDOWS + _Py_BEGIN_SUPPRESS_IPH + handle = (HANDLE)_get_osfhandle(fd); + _Py_END_SUPPRESS_IPH + if (handle == INVALID_HANDLE_VALUE) { + if (raise) + PyErr_SetFromErrno(PyExc_OSError); + return -1; + } + + if (inheritable) + flags = HANDLE_FLAG_INHERIT; + else + flags = 0; + if (!SetHandleInformation(handle, HANDLE_FLAG_INHERIT, flags)) { + if (raise) + PyErr_SetFromWindowsErr(0); + return -1; + } + return 0; + +#else + +#if defined(HAVE_SYS_IOCTL_H) && defined(FIOCLEX) && defined(FIONCLEX) if (ioctl_works != 0 && raise != 0) { /* fast-path: ioctl() only requires one syscall */ /* caveat: raise=0 is an indicator that we must be async-signal-safe * thus avoid using ioctl() so we skip the fast-path. */ if (inheritable) - err = ioctl(fd, FIONCLEX, NULL); + request = FIONCLEX; else - err = ioctl(fd, FIOCLEX, NULL); + request = FIOCLEX; + err = ioctl(fd, request, NULL); if (!err) { ioctl_works = 1; return 0; } + if (errno != ENOTTY && errno != EACCES) { if (raise) PyErr_SetFromErrno(PyExc_OSError); @@ -483,18 +520,19 @@ set_inheritable(int fd, int inheritable, int raise, int *atomic_flag_works) } else { /* Issue #22258: Here, ENOTTY means "Inappropriate ioctl for - device". The ioctl is declared but not supported by the - kernel. Remember that ioctl() doesn't work. It is the - case on Illumos-based OS for example. + device". The ioctl is declared but not supported by the kernel. + Remember that ioctl() doesn't work. It is the case on + Illumos-based OS for example. - Issue #27057: When SELinux policy disallows ioctl it will - fail with EACCES. While FIOCLEX is safe operation it may - be unavailable because ioctl was denied altogether. This - can be the case on Android. */ + Issue #27057: When SELinux policy disallows ioctl it will fail + with EACCES. While FIOCLEX is safe operation it may be + unavailable because ioctl was denied altogether. + This can be the case on Android. */ ioctl_works = 0; } /* fallback to fcntl() if ioctl() does not work */ } +#endif /* slow-path: fcntl() requires two syscalls */ flags = fcntl(fd, F_GETFD); @@ -523,6 +561,7 @@ set_inheritable(int fd, int inheritable, int raise, int *atomic_flag_works) return -1; } return 0; +#endif } /* Make the file descriptor non-inheritable.