* \param fd The file descriptor to read from.
* \param iov Scatter/gather array used in readv().
* \param iovcnt Number of elements in \a iov.
- * \param rfds An optional fd set pointer.
* \param num_bytes Result pointer. Contains the number of bytes read from \a fd.
*
- * If rfds is not NULL and the (non-blocking) file descriptor fd is not set in
- * rfds, this function returns early without doing anything. Otherwise it tries
- * to read up to sz bytes from fd, where sz is the sum of the lengths of all
- * vectors in iov. Like \ref xwrite(), EAGAIN and EINTR are not considered
- * error conditions. However, EOF is.
+ * This function tries to read up to sz bytes from fd, where sz is the sum of
+ * the lengths of all vectors in iov. Like \ref xwrite(), EAGAIN and EINTR are
+ * not considered error conditions. However, EOF is.
*
* \return Zero or a negative error code. If the underlying call to readv(2)
* returned zero (indicating an end of file condition) or failed for some
*
* \sa \ref xwrite(), read(2), readv(2).
*/
-int readv_nonblock(int fd, struct iovec *iov, int iovcnt, fd_set *rfds,
- size_t *num_bytes)
+int readv_nonblock(int fd, struct iovec *iov, int iovcnt, size_t *num_bytes)
{
int ret, i, j;
*num_bytes = 0;
- /*
- * Avoid a shortcoming of select(): Reads from a non-blocking fd might
- * return EAGAIN even if FD_ISSET() returns true. However, FD_ISSET()
- * returning false definitely means that no data can currently be read.
- * This is the common case, so it is worth to avoid the overhead of the
- * read() system call in this case.
- */
- if (rfds && !FD_ISSET(fd, rfds))
- return 0;
-
for (i = 0, j = 0; i < iovcnt;) {
-
/* fix up the first iov */
assert(j < iov[i].iov_len);
iov[i].iov_base += j;
* \param fd The file descriptor to read from.
* \param buf The buffer to read data to.
* \param sz The size of \a buf.
- * \param rfds \see \ref readv_nonblock().
* \param num_bytes \see \ref readv_nonblock().
*
* This is a simple wrapper for readv_nonblock() which uses an iovec with a single
*
* \return The return value of the underlying call to readv_nonblock().
*/
-int read_nonblock(int fd, void *buf, size_t sz, fd_set *rfds, size_t *num_bytes)
+int read_nonblock(int fd, void *buf, size_t sz, size_t *num_bytes)
{
struct iovec iov = {.iov_base = buf, .iov_len = sz};
- return readv_nonblock(fd, &iov, 1, rfds, num_bytes);
+ return readv_nonblock(fd, &iov, 1, num_bytes);
}
/**
* \param fd The file descriptor to receive from.
* \param pattern The expected pattern.
* \param bufsize The size of the internal buffer.
- * \param rfds Passed to read_nonblock().
*
* This function tries to read at most \a bufsize bytes from the non-blocking
* file descriptor \a fd. If at least \p strlen(\a pattern) bytes have been
*
* \sa \ref read_nonblock(), \sa strncasecmp(3).
*/
-int read_pattern(int fd, const char *pattern, size_t bufsize, fd_set *rfds)
+int read_pattern(int fd, const char *pattern, size_t bufsize)
{
size_t n, len;
char *buf = alloc(bufsize + 1);
- int ret = read_nonblock(fd, buf, bufsize, rfds, &n);
+ int ret = read_nonblock(fd, buf, bufsize, &n);
buf[n] = '\0';
if (ret < 0)
return !stat(fn, &statbuf);
}
-/**
- * Paraslash's wrapper for select(2).
- *
- * It calls select(2) (with no exceptfds) and starts over if select() was
- * interrupted by a signal.
- *
- * \param n The highest-numbered descriptor in any of the two sets, plus 1.
- * \param readfds fds that should be checked for readability.
- * \param writefds fds that should be checked for writablility.
- * \param timeout_tv upper bound on the amount of time elapsed before select()
- * returns.
- *
- * \return The return value of the underlying select() call on success, the
- * negative system error code on errors.
- *
- * All arguments are passed verbatim to select(2).
- * \sa select(2) select_tut(2).
- */
-int para_select(int n, fd_set *readfds, fd_set *writefds,
- struct timeval *timeout_tv)
-{
- int ret;
- do
- ret = select(n, readfds, writefds, NULL, timeout_tv);
- while (ret < 0 && errno == EINTR);
- if (ret < 0)
- return -ERRNO_TO_PARA_ERROR(errno);
- return ret;
-}
-
/**
* Set a file descriptor to blocking mode.
*
return 1;
}
-/**
- * Set a file descriptor in a fd_set.
- *
- * \param fd The file descriptor to be set.
- * \param fds The file descriptor set.
- * \param max_fileno Highest-numbered file descriptor.
- *
- * This wrapper for FD_SET() passes its first two arguments to \p FD_SET. Upon
- * return, \a max_fileno contains the maximum of the old_value and \a fd.
- *
- * \sa \ref para_select.
-*/
-void para_fd_set(int fd, fd_set *fds, int *max_fileno)
-{
- assert(fd >= 0 && fd < FD_SETSIZE);
-#if 0
- {
- int flags = fcntl(fd, F_GETFL);
- if (!(flags & O_NONBLOCK)) {
- PARA_EMERG_LOG("fd %d is a blocking file descriptor\n", fd);
- exit(EXIT_FAILURE);
- }
- }
-#endif
- FD_SET(fd, fds);
- *max_fileno = PARA_MAX(*max_fileno, fd);
-}
-
/**
* Paraslash's wrapper for mmap.
*
return -ERRNO_TO_PARA_ERROR(err);
}
+/**
+ * Simple wrapper for poll(2).
+ *
+ * It calls poll(2) and starts over if the call was interrupted by a signal.
+ *
+ * \param fds See poll(2).
+ * \param nfds See poll(2).
+ * \param timeout See poll(2).
+ *
+ * \return The return value of the underlying poll() call on success, the
+ * negative paraslash error code on errors.
+ *
+ * All arguments are passed verbatim to poll(2).
+ */
+int xpoll(struct pollfd *fds, nfds_t nfds, int timeout)
+{
+ int ret;
+
+ do
+ ret = poll(fds, nfds, timeout);
+ while (ret < 0 && errno == EINTR);
+ return ret < 0? -ERRNO_TO_PARA_ERROR(errno) : ret;
+}
+
+/**
+ * Check a file descriptor for readability.
+ *
+ * \param fd The file descriptor.
+ *
+ * \return positive if fd is ready for reading, zero if it isn't, negative if
+ * an error occurred.
+ *
+ * \sa \ref write_ok().
+ */
+int read_ok(int fd)
+{
+ struct pollfd pfd = {.fd = fd, .events = POLLIN};
+ int ret = xpoll(&pfd, 1, 0);
+ return ret < 0? ret : pfd.revents & POLLIN;
+}
+
/**
* Check a file descriptor for writability.
*
*
* \return positive if fd is ready for writing, zero if it isn't, negative if
* an error occurred.
+ *
+ * \sa \ref read_ok().
*/
-
int write_ok(int fd)
{
- struct timeval tv;
- fd_set wfds;
-
- FD_ZERO(&wfds);
- FD_SET(fd, &wfds);
- tv.tv_sec = 0;
- tv.tv_usec = 0;
- return para_select(fd + 1, NULL, &wfds, &tv);
+ struct pollfd pfd = {.fd = fd, .events = POLLOUT};
+ int ret = xpoll(&pfd, 1, 0);
+ return ret < 0? ret : pfd.revents & POLLOUT;
}
/**