blob: ae6a7fc7388797b7e2fe4166ff23ef89b0f02723 [file]
/*
* Copyright 2017, Data61, CSIRO (ABN 41 687 119 230)
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <assert.h>
#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <sys/select.h>
#include <muslcsys/io.h>
#include "sys_io.h"
static void fdset_to_sockset(int maxfd, fd_set *fds)
{
muslcsys_fd_t *fdt;
int sockfd;
if (maxfd <= FIRST_USER_FD || !fds) {
return;
}
for (int i = FIRST_USER_FD; i < maxfd; i++) {
fdt = get_fd_struct(i);
if (fdt->filetype == FILE_TYPE_SOCKET) {
sockfd = *(int *)fdt->data;
if (FD_ISSET(i, fds)) {
FD_CLR(i, fds);
FD_SET(sockfd, fds);
}
}
}
}
static void sockset_to_fdset(int maxfd, fd_set *fds)
{
muslcsys_fd_t *fdt;
int sockfd;
if (maxfd <= FIRST_USER_FD || !fds) {
return;
}
for (int i = FIRST_USER_FD; i < maxfd; i++) {
fdt = get_fd_struct(i);
if (fdt->filetype == FILE_TYPE_SOCKET) {
sockfd = *(int *)fdt->data;
if (FD_ISSET(sockfd, fds)) {
FD_CLR(sockfd, fds);
FD_SET(i, fds);
}
}
}
}
static int find_max_sockfd(int nfds)
{
muslcsys_fd_t *fdt;
int sockfd;
int max = 0;
for (int i = FIRST_USER_FD; i < nfds; i++) {
fdt = get_fd_struct(i);
if (fdt->filetype == FILE_TYPE_SOCKET) {
sockfd = *(int *)fdt->data;
if (sockfd > max) {
max = sockfd;
}
}
}
return max;
}
int sock_select(int nfds) __attribute__((weak));
long camkes_sys__newselect(va_list ap)
{
int nfds = va_arg(ap, int);
fd_set *readfds = va_arg(ap, fd_set *);
fd_set *writefds = va_arg(ap, fd_set *);
fd_set *exceptfds = va_arg(ap, fd_set *);
struct timeval *timeout = va_arg(ap, struct timeval *);
int retval;
if (sock_select && sock_data) {
fdset_to_sockset(nfds, readfds);
fdset_to_sockset(nfds, writefds);
fdset_to_sockset(nfds, exceptfds);
if (readfds) {
memcpy((char *)sock_data, readfds, sizeof(fd_set));
}
if (writefds) {
memcpy((char *)sock_data + sizeof(fd_set), writefds, sizeof(fd_set));
}
if (exceptfds) {
memcpy((char *)sock_data + sizeof(fd_set) * 2, exceptfds, sizeof(fd_set));
}
if (timeout) {
memcpy((char *)sock_data + sizeof(fd_set) * 3, timeout, sizeof(struct timeval));
}
retval = sock_select(find_max_sockfd(nfds) + 1);
if (readfds) {
memcpy(readfds, (char *)sock_data, sizeof(fd_set));
}
if (writefds) {
memcpy(writefds, (char *)sock_data + sizeof(fd_set), sizeof(fd_set));
}
if (exceptfds) {
memcpy(exceptfds, (char *)sock_data + sizeof(fd_set) * 2, sizeof(fd_set));
}
if (timeout) {
memcpy(timeout, (char *)sock_data + sizeof(fd_set) * 3, sizeof(struct timeval));
}
sockset_to_fdset(nfds, readfds);
sockset_to_fdset(nfds, writefds);
sockset_to_fdset(nfds, exceptfds);
return retval;
} else {
assert(!"sys__newselect not implemented");
return -ENOSYS;
}
}