| /* |
| * 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; |
| } |
| } |