-/*
- * Copyright (C) 2006 Andre Noll <maan@tuebingen.mpg.de>
- *
- * Licensed under the GPL v2. For licencing details see COPYING.
- */
+/* Copyright (C) 2006 Andre Noll <maan@tuebingen.mpg.de>, see file COPYING. */
/** \file fd.c Helper functions for file descriptor handling. */
#include <sys/types.h>
#include <dirent.h>
#include <sys/mman.h>
+#include <poll.h>
#include "para.h"
#include "error.h"
* \param rfds An optional fd set pointer.
* \param num_bytes Result pointer. Contains the number of bytes read from \a fd.
*
- * If \a rfds is not \p NULL and the (non-blocking) file descriptor \a fd is
- * not set in \a rfds, this function returns early without doing anything.
- * Otherwise The function tries to read up to \a sz bytes from \a fd, where \a
- * sz is the sum of the lengths of all vectors in \a iov. As for xwrite(),
- * \p EAGAIN is not considered an error condition. However, \p EOF is.
+ * 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.
*
* \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
- * reason other than \p EAGAIN, a negative error code is returned.
+ * reason other than EAGAIN or EINTR, a negative error code is returned.
*
* In any case, \a num_bytes contains the number of bytes that have been
* successfully read from \a fd (zero if the first readv() call failed with
if (ret == 0)
return -E_EOF;
if (ret < 0) {
- if (errno == EAGAIN)
+ if (errno == EAGAIN || errno == EINTR)
return 0;
return -ERRNO_TO_PARA_ERROR(errno);
}
*
* \param fn The file name.
*
- * \return Non-zero iff file exists.
+ * \return True iff file exists.
*/
-int file_exists(const char *fn)
+bool file_exists(const char *fn)
{
struct stat statbuf;
* \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.
+ * \param timeout Upper bound in milliseconds.
*
* \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 para_select(int n, fd_set *readfds, fd_set *writefds, int timeout)
{
int ret;
+ struct timeval tv;
+
+ ms2tv(timeout, &tv);
do
- ret = select(n, readfds, writefds, NULL, timeout_tv);
+ ret = select(n, readfds, writefds, NULL, &tv);
while (ret < 0 && errno == EINTR);
if (ret < 0)
return -ERRNO_TO_PARA_ERROR(errno);
*max_fileno = PARA_MAX(*max_fileno, fd);
}
-/**
- * Paraslash's wrapper for fgets(3).
- *
- * \param line Pointer to the buffer to store the line.
- * \param size The size of the buffer given by \a line.
- * \param f The stream to read from.
- *
- * \return Unlike the standard fgets() function, an integer value
- * is returned. On success, this function returns 1. On errors, -E_FGETS
- * is returned. A zero return value indicates an end of file condition.
- */
-__must_check int para_fgets(char *line, int size, FILE *f)
-{
-again:
- if (fgets(line, size, f))
- return 1;
- if (feof(f))
- return 0;
- if (!ferror(f))
- return -E_FGETS;
- if (errno != EINTR) {
- PARA_ERROR_LOG("%s\n", strerror(errno));
- return -E_FGETS;
- }
- clearerr(f);
- goto again;
-}
-
/**
* Paraslash's wrapper for mmap.
*
* PROT_EXEC PROT_READ PROT_WRITE.
* \param flags Exactly one of MAP_SHARED and MAP_PRIVATE.
* \param fd The file to mmap from.
- * \param offset Mmap start.
* \param map Result pointer.
*
* \return Standard.
*
* \sa mmap(2).
*/
-int para_mmap(size_t length, int prot, int flags, int fd, off_t offset,
- void *map)
+int para_mmap(size_t length, int prot, int flags, int fd, void *map)
{
void **m = map;
errno = EINVAL;
if (!length)
goto err;
- *m = mmap(NULL, length, prot, flags, fd, offset);
+ *m = mmap(NULL, length, prot, flags, fd, (off_t)0);
if (*m != MAP_FAILED)
return 1;
err:
if (S_ISDIR(file_status.st_mode))
goto out;
- ret = para_mmap(*size, mmap_prot, mmap_flags, fd, 0, map);
+ ret = para_mmap(*size, mmap_prot, mmap_flags, fd, map);
out:
if (ret < 0 || !fd_ptr)
close(fd);
return -ERRNO_TO_PARA_ERROR(err);
}
+static 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;
}
/**