mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-02-12 01:08:00 +00:00
Fix ioctl() and FIONREAD for sockets on Windows
This change fixes an issue where using FIONREAD would cause control flow to jump to null, due to a _weaken() reference that I refactored long ago
This commit is contained in:
parent
1260f9d0ed
commit
6b10f4d0b6
6 changed files with 77 additions and 9 deletions
|
@ -38,6 +38,7 @@
|
||||||
#include "libc/nt/iphlpapi.h"
|
#include "libc/nt/iphlpapi.h"
|
||||||
#include "libc/nt/runtime.h"
|
#include "libc/nt/runtime.h"
|
||||||
#include "libc/nt/struct/ipadapteraddresses.h"
|
#include "libc/nt/struct/ipadapteraddresses.h"
|
||||||
|
#include "libc/nt/thunk/msabi.h"
|
||||||
#include "libc/nt/winsock.h"
|
#include "libc/nt/winsock.h"
|
||||||
#include "libc/runtime/runtime.h"
|
#include "libc/runtime/runtime.h"
|
||||||
#include "libc/runtime/stack.h"
|
#include "libc/runtime/stack.h"
|
||||||
|
@ -59,6 +60,8 @@
|
||||||
#define MAX_UNICAST_ADDR 32
|
#define MAX_UNICAST_ADDR 32
|
||||||
#define MAX_NAME_CLASH ((int)('z' - 'a')) /* Allow a..z */
|
#define MAX_NAME_CLASH ((int)('z' - 'a')) /* Allow a..z */
|
||||||
|
|
||||||
|
__msabi extern typeof(__sys_ioctlsocket_nt) *const __imp_ioctlsocket;
|
||||||
|
|
||||||
static struct HostAdapterInfoNode {
|
static struct HostAdapterInfoNode {
|
||||||
struct HostAdapterInfoNode *next;
|
struct HostAdapterInfoNode *next;
|
||||||
char name[IFNAMSIZ]; /* Obtained from FriendlyName */
|
char name[IFNAMSIZ]; /* Obtained from FriendlyName */
|
||||||
|
@ -76,7 +79,7 @@ static int ioctl_default(int fd, unsigned long request, void *arg) {
|
||||||
} else if (__isfdopen(fd)) {
|
} else if (__isfdopen(fd)) {
|
||||||
if (g_fds.p[fd].kind == kFdSocket) {
|
if (g_fds.p[fd].kind == kFdSocket) {
|
||||||
handle = g_fds.p[fd].handle;
|
handle = g_fds.p[fd].handle;
|
||||||
if ((rc = _weaken(__sys_ioctlsocket_nt)(handle, request, arg)) != -1) {
|
if ((rc = __imp_ioctlsocket(handle, request, arg)) != -1) {
|
||||||
return rc;
|
return rc;
|
||||||
} else {
|
} else {
|
||||||
return _weaken(__winsockerr)();
|
return _weaken(__winsockerr)();
|
||||||
|
@ -97,7 +100,7 @@ static int ioctl_fionread(int fd, uint32_t *arg) {
|
||||||
} else if (__isfdopen(fd)) {
|
} else if (__isfdopen(fd)) {
|
||||||
handle = g_fds.p[fd].handle;
|
handle = g_fds.p[fd].handle;
|
||||||
if (g_fds.p[fd].kind == kFdSocket) {
|
if (g_fds.p[fd].kind == kFdSocket) {
|
||||||
if ((rc = _weaken(__sys_ioctlsocket_nt)(handle, FIONREAD, arg)) != -1) {
|
if ((rc = __imp_ioctlsocket(handle, FIONREAD, arg)) != -1) {
|
||||||
return rc;
|
return rc;
|
||||||
} else {
|
} else {
|
||||||
return _weaken(__winsockerr)();
|
return _weaken(__winsockerr)();
|
||||||
|
|
|
@ -39,7 +39,7 @@ struct RecvArgs {
|
||||||
struct NtIovec iovnt[16];
|
struct NtIovec iovnt[16];
|
||||||
};
|
};
|
||||||
|
|
||||||
static textwindows int sys_recv_nt_start(int64_t handle,
|
textwindows static int sys_recv_nt_start(int64_t handle,
|
||||||
struct NtOverlapped *overlap,
|
struct NtOverlapped *overlap,
|
||||||
uint32_t *flags, void *arg) {
|
uint32_t *flags, void *arg) {
|
||||||
struct RecvArgs *args = arg;
|
struct RecvArgs *args = arg;
|
||||||
|
|
|
@ -42,7 +42,7 @@ struct RecvFromArgs {
|
||||||
struct NtIovec iovnt[16];
|
struct NtIovec iovnt[16];
|
||||||
};
|
};
|
||||||
|
|
||||||
static textwindows int sys_recvfrom_nt_start(int64_t handle,
|
textwindows static int sys_recvfrom_nt_start(int64_t handle,
|
||||||
struct NtOverlapped *overlap,
|
struct NtOverlapped *overlap,
|
||||||
uint32_t *flags, void *arg) {
|
uint32_t *flags, void *arg) {
|
||||||
struct RecvFromArgs *args = arg;
|
struct RecvFromArgs *args = arg;
|
||||||
|
|
|
@ -38,7 +38,7 @@ struct SendArgs {
|
||||||
struct NtIovec iovnt[16];
|
struct NtIovec iovnt[16];
|
||||||
};
|
};
|
||||||
|
|
||||||
static textwindows int sys_send_nt_start(int64_t handle,
|
textwindows static int sys_send_nt_start(int64_t handle,
|
||||||
struct NtOverlapped *overlap,
|
struct NtOverlapped *overlap,
|
||||||
uint32_t *flags, void *arg) {
|
uint32_t *flags, void *arg) {
|
||||||
struct SendArgs *args = arg;
|
struct SendArgs *args = arg;
|
||||||
|
|
|
@ -19,10 +19,6 @@
|
||||||
dir=libc/sysv/consts
|
dir=libc/sysv/consts
|
||||||
. libc/sysv/gen.sh
|
. libc/sysv/gen.sh
|
||||||
|
|
||||||
# syscon errno EALREADY 114 114 37 37 37 37 37 10037 # connection already in progress; bsd consensus; WSAEALREADY; raised by connect(2), send(2), ip(7)
|
|
||||||
# syscon errno EINPROGRESS 115 115 36 36 36 36 36 10036 # bsd consensus; WSAEINPROGRESS; raised by connect(2) w/ O_NONBLOCK
|
|
||||||
# syscon errno EISCONN 106 106 56 56 56 56 56 10056 # socket is connected; bsd consensus; WSAEISCONN; raised by connect(2), send(2), unix(7), ip(7)
|
|
||||||
|
|
||||||
# The Fifth Bell System, Community Edition
|
# The Fifth Bell System, Community Edition
|
||||||
# » catalogue of carnage
|
# » catalogue of carnage
|
||||||
#
|
#
|
||||||
|
|
69
test/posix/socket_fionread_test.c
Normal file
69
test/posix/socket_fionread_test.c
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <cosmo.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <poll.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
|
||||||
|
// create server socket
|
||||||
|
int server_fd;
|
||||||
|
struct sockaddr_in address;
|
||||||
|
int addrlen = sizeof(address);
|
||||||
|
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
|
||||||
|
return 1;
|
||||||
|
address.sin_family = AF_INET;
|
||||||
|
address.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
||||||
|
address.sin_port = 0; // let os assign random port
|
||||||
|
if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)))
|
||||||
|
return 2;
|
||||||
|
if (getsockname(server_fd, (struct sockaddr *)&address,
|
||||||
|
(socklen_t *)&addrlen))
|
||||||
|
return 3;
|
||||||
|
if (listen(server_fd, SOMAXCONN))
|
||||||
|
return 4;
|
||||||
|
|
||||||
|
// create client socket
|
||||||
|
int client_fd;
|
||||||
|
if ((client_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
|
||||||
|
return 6;
|
||||||
|
if (connect(client_fd, (struct sockaddr *)&address, sizeof(address)))
|
||||||
|
return 7;
|
||||||
|
|
||||||
|
// accept client and send data
|
||||||
|
int server_client_fd;
|
||||||
|
if ((server_client_fd = accept(server_fd, 0, 0)) == -1)
|
||||||
|
return 8;
|
||||||
|
if (write(server_client_fd, "hi", 2) != 2)
|
||||||
|
return 9;
|
||||||
|
|
||||||
|
// poll to be safe (important for mac/bsd)
|
||||||
|
struct pollfd fds[] = {{client_fd, POLLIN}};
|
||||||
|
if (poll(fds, 1, -1u) != 1)
|
||||||
|
return 10;
|
||||||
|
|
||||||
|
// ask how many bytes we can read
|
||||||
|
uint32_t bytes_available;
|
||||||
|
if (ioctl(client_fd, FIONREAD, &bytes_available))
|
||||||
|
return 11;
|
||||||
|
if (bytes_available != 2) {
|
||||||
|
printf("wut %d\n", bytes_available);
|
||||||
|
return 12;
|
||||||
|
}
|
||||||
|
|
||||||
|
// clean up
|
||||||
|
if (close(client_fd))
|
||||||
|
return 13;
|
||||||
|
if (close(server_fd))
|
||||||
|
return 14;
|
||||||
|
|
||||||
|
CheckForMemoryLeaks();
|
||||||
|
}
|
Loading…
Reference in a new issue