aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlexander Færøy <ahf@torproject.org>2017-02-27 15:37:31 +0100
committerAlexander Færøy <ahf@torproject.org>2017-03-01 21:26:26 +0100
commit498287b3c340739bede9a3fa95ea23b6ae650bf3 (patch)
tree1cab67defeabceb27fe22c40cdb94c95e901bc7a /src
parenta0a4f8ae5d94a667ad431e487e08bc935a6989b5 (diff)
downloadtor-498287b3c340739bede9a3fa95ea23b6ae650bf3.tar.gz
tor-498287b3c340739bede9a3fa95ea23b6ae650bf3.zip
Add compatibility function for fgets(3).
This patch adds the `tor_fgets()` function to our compatibility layer. `tor_fgets()` adds an additional check for whether the error-bit have been enabled for the given file stream, if that is the case and `errno` is set to `EAGAIN` we make sure that we always return NULL. Unfortunately `fgets(3)` behaves differently on different versions of the C library. See: https://bugs.torproject.org/21416 See: https://bugs.torproject.org/20988
Diffstat (limited to 'src')
-rw-r--r--src/common/compat.c39
-rw-r--r--src/common/compat.h2
2 files changed, 41 insertions, 0 deletions
diff --git a/src/common/compat.c b/src/common/compat.c
index 0dbede6bed..da4283fbaa 100644
--- a/src/common/compat.c
+++ b/src/common/compat.c
@@ -3476,6 +3476,45 @@ tor_getpass(const char *prompt, char *output, size_t buflen)
#endif
}
+/** Read at most one less than the number of characters specified by
+ * <b>size</b> from the given <b>stream</b> and store it in <b>str</b>.
+ *
+ * Reading stops when a newline character is found or at EOF or error. If any
+ * characters are read and there's no error, a trailing NUL byte is appended to
+ * the end of <b>str</b>.
+ *
+ * Upon successful completion, this function returns a pointer to the string
+ * <b>str</b>. If EOF occurs before any characters are read the function will
+ * return NULL and the content of <b>str</b> is unchanged. Upon error, the
+ * function returns NULL and the caller must check for error using foef(3) and
+ * ferror(3).
+ */
+char *
+tor_fgets(char *str, int size, FILE *stream)
+{
+ char *ret;
+
+ /* Reset errno before our call to fgets(3) to avoid a situation where the
+ * caller is calling us again because we just returned NULL and errno ==
+ * EAGAIN, but when they call us again we will always return NULL because the
+ * error flag on the file handler remains set and errno is set to EAGAIN.
+ */
+ errno = 0;
+
+ ret = fgets(str, size, stream);
+
+ /* FreeBSD, OpenBSD, Linux (glibc), and Linux (musl) seem to disagree about
+ * what to do in the given situation. We check if the stream has been flagged
+ * with an error-bit and return NULL in that situation if errno is also set
+ * to EAGAIN.
+ */
+ if (ferror(stream) && errno == EAGAIN) {
+ return NULL;
+ }
+
+ return ret;
+}
+
/** Return the amount of free disk space we have permission to use, in
* bytes. Return -1 if the amount of free space can't be determined. */
int64_t
diff --git a/src/common/compat.h b/src/common/compat.h
index ee1c9454de..1f51ece61f 100644
--- a/src/common/compat.h
+++ b/src/common/compat.h
@@ -740,6 +740,8 @@ STATIC int tor_ersatz_socketpair(int family, int type, int protocol,
ssize_t tor_getpass(const char *prompt, char *output, size_t buflen);
+char *tor_fgets(char *str, int size, FILE *stream);
+
/* This needs some of the declarations above so we include it here. */
#include "compat_threads.h"