diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 8b4e903f1..3f16c25a5 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,8 @@ +Fri Aug 11 14:47:00 2000 Corinna Vinschen + + * poll.cc: Allow any descriptor and any number of descriptors. + Allocate fd_set struct sdynamically. + Fri Aug 11 14:47:00 2000 Corinna Vinschen * poll.cc: Add bounds checking for file descriptors. Return POLLNVAL diff --git a/winsup/cygwin/poll.cc b/winsup/cygwin/poll.cc index 2e2851620..b0a5ebd29 100644 --- a/winsup/cygwin/poll.cc +++ b/winsup/cygwin/poll.cc @@ -8,44 +8,58 @@ Cygwin license. Please consult the file "CYGWIN_LICENSE" for details. */ -#include "winsup.h" #include +#include +#include "winsup.h" extern "C" int poll (struct pollfd *fds, unsigned int nfds, int timeout) { int max_fd = 0; - fd_set open_fds, read_fds, write_fds, except_fds; + fd_set *open_fds, *read_fds, *write_fds, *except_fds; struct timeval tv = { timeout / 1000, (timeout % 1000) * 1000 }; - FD_ZERO (&open_fds); - FD_ZERO (&read_fds); - FD_ZERO (&write_fds); - FD_ZERO (&except_fds); + for (unsigned int i = 0; i < nfds; ++i) + if (fds[i].fd > max_fd) + max_fd = fds[i].fd; + + size_t fds_size = howmany(max_fd + 1, NFDBITS) * sizeof (fd_mask); + + open_fds = (fd_set *) alloca (fds_size); + read_fds = (fd_set *) alloca (fds_size); + write_fds = (fd_set *) alloca (fds_size); + except_fds = (fd_set *) alloca (fds_size); + + if (!open_fds || !read_fds || !write_fds || !except_fds) + { + set_errno (ENOMEM); + return -1; + } + + memset (open_fds, 0, fds_size); + memset (read_fds, 0, fds_size); + memset (write_fds, 0, fds_size); + memset (except_fds, 0, fds_size); for (unsigned int i = 0; i < nfds; ++i) - if (fds[i].fd < FD_SETSIZE - && !dtable.not_open (fds[i].fd)) + if (!dtable.not_open (fds[i].fd)) { - FD_SET (fds[i].fd, &open_fds); + FD_SET (fds[i].fd, open_fds); if (fds[i].events & POLLIN) - FD_SET (fds[i].fd, &read_fds); + FD_SET (fds[i].fd, read_fds); if (fds[i].events & POLLOUT) - FD_SET (fds[i].fd, &write_fds); + FD_SET (fds[i].fd, write_fds); if (fds[i].events & POLLPRI) - FD_SET (fds[i].fd, &except_fds); - if (fds[i].fd > max_fd) - max_fd = fds[i].fd; + FD_SET (fds[i].fd, except_fds); } - int ret = cygwin_select (max_fd + 1, &read_fds, &write_fds, &except_fds, + int ret = cygwin_select (max_fd + 1, read_fds, write_fds, except_fds, timeout < 0 ? NULL : &tv); for (unsigned int i = 0; i < nfds; ++i) { - if (fds[i].fd >= FD_SETSIZE - || !FD_ISSET (fds[i].fd, &open_fds)) + if (!FD_ISSET (fds[i].fd, open_fds)) fds[i].revents = POLLNVAL; else if (dtable.not_open(fds[i].fd)) fds[i].revents = POLLHUP; @@ -54,11 +68,11 @@ poll (struct pollfd *fds, unsigned int nfds, int timeout) else { fds[i].revents = 0; - if (FD_ISSET (fds[i].fd, &read_fds)) + if (FD_ISSET (fds[i].fd, read_fds)) fds[i].revents |= POLLIN; - if (FD_ISSET (fds[i].fd, &write_fds)) + if (FD_ISSET (fds[i].fd, write_fds)) fds[i].revents |= POLLOUT; - if (FD_ISSET (fds[i].fd, &except_fds)) + if (FD_ISSET (fds[i].fd, except_fds)) fds[i].revents |= POLLPRI; } }