//////////////////////// \brief SysSelect(nfds, readfds, writefds, exceptfds, timeout) Set a file handle's mode/status flags \param nfds (int) number of file descriptors \param readfds (fd_set) check for readable fds \param writefds (fd_set) check for writable fds \param exceptfds (fd_set) check for exceptions on fds \param timeout (timespec) timeout period \return number of events on success, n
| 2088 | /// \return number of events on success, negative error code on failure |
| 2089 | ///////////////////////////// |
| 2090 | long SysSelect(regs64_t* r){ |
| 2091 | process_t* currentProcess = Scheduler::GetCurrentProcess(); |
| 2092 | |
| 2093 | int nfds = static_cast<int>(SC_ARG0(r)); |
| 2094 | fd_set_t* readFdsMask = reinterpret_cast<fd_set_t*>(SC_ARG1(r)); |
| 2095 | fd_set_t* writeFdsMask = reinterpret_cast<fd_set_t*>(SC_ARG2(r)); |
| 2096 | fd_set_t* exceptFdsMask = reinterpret_cast<fd_set_t*>(SC_ARG3(r)); |
| 2097 | timespec_t* timeout = reinterpret_cast<timespec_t*>(SC_ARG4(r)); |
| 2098 | |
| 2099 | if(!((!readFdsMask || Memory::CheckUsermodePointer(SC_ARG1(r), sizeof(fd_set_t), currentProcess->addressSpace)) |
| 2100 | && (!writeFdsMask || Memory::CheckUsermodePointer(SC_ARG2(r), sizeof(fd_set_t), currentProcess->addressSpace)) |
| 2101 | && (!exceptFdsMask || Memory::CheckUsermodePointer(SC_ARG3(r), sizeof(fd_set_t), currentProcess->addressSpace)) |
| 2102 | && Memory::CheckUsermodePointer(SC_ARG4(r), sizeof(timespec_t), currentProcess->addressSpace))){ |
| 2103 | return -EFAULT; // Only return EFAULT if read/write/exceptfds is not null |
| 2104 | } |
| 2105 | |
| 2106 | List<Pair<fs_fd_t*, int>> readfds; |
| 2107 | List<Pair<fs_fd_t*, int>> writefds; |
| 2108 | List<Pair<fs_fd_t*, int>> exceptfds; |
| 2109 | |
| 2110 | auto getHandleSafe = [&](int fd) -> fs_fd_t* { |
| 2111 | if(static_cast<unsigned>(fd) > currentProcess->fileDescriptors.get_length()){ |
| 2112 | return nullptr; |
| 2113 | } |
| 2114 | return currentProcess->fileDescriptors[fd]; // If fd is null then this will return null as if out of range |
| 2115 | }; |
| 2116 | |
| 2117 | for(int i = 0; i < 128 && i * 8 < nfds; i++){ |
| 2118 | char read = 0, write = 0, except = 0; |
| 2119 | if(readFdsMask) { |
| 2120 | read = readFdsMask->fds_bits[i]; |
| 2121 | readFdsMask->fds_bits[i] = 0; // With select the fds are cleared to 0 unless they are ready |
| 2122 | } |
| 2123 | |
| 2124 | if(writeFdsMask){ |
| 2125 | write = writeFdsMask->fds_bits[i]; |
| 2126 | writeFdsMask->fds_bits[i] = 0; |
| 2127 | } |
| 2128 | |
| 2129 | if(exceptFdsMask){ |
| 2130 | except = exceptFdsMask->fds_bits[i]; |
| 2131 | exceptFdsMask->fds_bits[i] = 0; |
| 2132 | } |
| 2133 | |
| 2134 | for(int j = 0; j < 8 && (i * 8 + j) < nfds; j++){ |
| 2135 | if((read >> j) & 0x1){ |
| 2136 | fs_fd_t* h = getHandleSafe(i * 8 + j); |
| 2137 | if(!h){ |
| 2138 | return -EBADF; |
| 2139 | } |
| 2140 | |
| 2141 | readfds.add_back(Pair<fs_fd_t*, int>(h, i * 8 + j)); |
| 2142 | } |
| 2143 | |
| 2144 | if((write >> j) & 0x1){ |
| 2145 | fs_fd_t* h = getHandleSafe(i * 8 + j); |
| 2146 | if(!h){ |
| 2147 | return -EBADF; |
nothing calls this directly
no test coverage detected