mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-10 13:13:44 +01:00
Remove fgets() compatbility function and related tests.
This patch removes the `tor_fgets()` wrapper around `fgets(3)` since it is no longer needed. The function was created due to inconsistency between the returned values of `fgets(3)` on different versions of Unix when using `fgets(3)` on non-blocking file descriptors, but with the recent changes in bug #21654 we switch from unbuffered to direct I/O on non-blocking file descriptors in our utility module. We continue to use `fgets(3)` directly in the geoip and dirserv module since this usage is considered safe. This patch also removes the test-case that was created to detect differences in the implementation of `fgets(3)` as well as the changes file since these changes was not included in any releases yet. See: https://bugs.torproject.org/21654
This commit is contained in:
parent
02ef06516e
commit
02fc0a5ecf
@ -1,4 +0,0 @@
|
||||
o Minor bugfixes (portability):
|
||||
- Add Tor compatibility function for fgets(3) due to inconsistency of
|
||||
returned values in different supported C libraries. This fixes unit test
|
||||
failures reported on FreeBSD. Fixes bug 20988.
|
@ -3476,45 +3476,6 @@ 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
|
||||
|
@ -740,8 +740,6 @@ 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"
|
||||
|
||||
|
@ -2701,7 +2701,7 @@ dirserv_read_measured_bandwidths(const char *from_file,
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!tor_fgets(line, sizeof(line), fp)
|
||||
if (!fgets(line, sizeof(line), fp)
|
||||
|| !strlen(line) || line[strlen(line)-1] != '\n') {
|
||||
log_warn(LD_DIRSERV, "Long or truncated time in bandwidth file: %s",
|
||||
escaped(line));
|
||||
@ -2731,7 +2731,7 @@ dirserv_read_measured_bandwidths(const char *from_file,
|
||||
|
||||
while (!feof(fp)) {
|
||||
measured_bw_line_t parsed_line;
|
||||
if (tor_fgets(line, sizeof(line), fp) && strlen(line)) {
|
||||
if (fgets(line, sizeof(line), fp) && strlen(line)) {
|
||||
if (measured_bw_line_parse(&parsed_line, line) != -1) {
|
||||
/* Also cache the line for dirserv_get_bandwidth_for_router() */
|
||||
dirserv_cache_measured_bw(&parsed_line, file_time);
|
||||
|
@ -346,7 +346,7 @@ geoip_load_file(sa_family_t family, const char *filename)
|
||||
(family == AF_INET) ? "IPv4" : "IPv6", filename);
|
||||
while (!feof(f)) {
|
||||
char buf[512];
|
||||
if (tor_fgets(buf, (int)sizeof(buf), f) == NULL)
|
||||
if (fgets(buf, (int)sizeof(buf), f) == NULL)
|
||||
break;
|
||||
crypto_digest_add_bytes(geoip_digest_env, buf, strlen(buf));
|
||||
/* FFFF track full country name. */
|
||||
|
@ -3940,116 +3940,6 @@ test_util_exit_status(void *ptr)
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32
|
||||
/* Check that fgets with a non-blocking pipe returns partial lines and sets
|
||||
* EAGAIN, returns full lines and sets no error, and returns NULL on EOF and
|
||||
* sets no error */
|
||||
static void
|
||||
test_util_fgets_eagain(void *ptr)
|
||||
{
|
||||
int test_pipe[2] = {-1, -1};
|
||||
int retval;
|
||||
ssize_t retlen;
|
||||
char *retptr;
|
||||
FILE *test_stream = NULL;
|
||||
char buf[4] = { 0 };
|
||||
|
||||
(void)ptr;
|
||||
|
||||
errno = 0;
|
||||
|
||||
/* Set up a pipe to test on */
|
||||
retval = pipe(test_pipe);
|
||||
tt_int_op(retval, OP_EQ, 0);
|
||||
|
||||
/* Set up the read-end to be non-blocking */
|
||||
retval = fcntl(test_pipe[0], F_SETFL, O_NONBLOCK);
|
||||
tt_int_op(retval, OP_EQ, 0);
|
||||
|
||||
/* Open it as a stdio stream */
|
||||
test_stream = fdopen(test_pipe[0], "r");
|
||||
tt_ptr_op(test_stream, OP_NE, NULL);
|
||||
|
||||
/* Send in a partial line */
|
||||
retlen = write(test_pipe[1], "A", 1);
|
||||
tt_int_op(retlen, OP_EQ, 1);
|
||||
retptr = tor_fgets(buf, sizeof(buf), test_stream);
|
||||
tt_int_op(errno, OP_EQ, EAGAIN);
|
||||
tt_ptr_op(retptr, OP_EQ, NULL);
|
||||
tt_str_op(buf, OP_EQ, "A");
|
||||
errno = 0;
|
||||
|
||||
/* Send in the rest */
|
||||
retlen = write(test_pipe[1], "B\n", 2);
|
||||
tt_int_op(retlen, OP_EQ, 2);
|
||||
retptr = tor_fgets(buf, sizeof(buf), test_stream);
|
||||
tt_int_op(errno, OP_EQ, 0);
|
||||
tt_ptr_op(retptr, OP_EQ, buf);
|
||||
tt_str_op(buf, OP_EQ, "B\n");
|
||||
errno = 0;
|
||||
memset(buf, '\0', sizeof(buf));
|
||||
|
||||
/* Send in a full line */
|
||||
retlen = write(test_pipe[1], "CD\n", 3);
|
||||
tt_int_op(retlen, OP_EQ, 3);
|
||||
retptr = tor_fgets(buf, sizeof(buf), test_stream);
|
||||
tt_int_op(errno, OP_EQ, 0);
|
||||
tt_ptr_op(retptr, OP_EQ, buf);
|
||||
tt_str_op(buf, OP_EQ, "CD\n");
|
||||
errno = 0;
|
||||
memset(buf, '\0', sizeof(buf));
|
||||
|
||||
/* Send in a partial line */
|
||||
retlen = write(test_pipe[1], "E", 1);
|
||||
tt_int_op(retlen, OP_EQ, 1);
|
||||
retptr = tor_fgets(buf, sizeof(buf), test_stream);
|
||||
tt_int_op(errno, OP_EQ, EAGAIN);
|
||||
tt_ptr_op(retptr, OP_EQ, NULL);
|
||||
tt_str_op(buf, OP_EQ, "E");
|
||||
errno = 0;
|
||||
|
||||
/* Send in the rest */
|
||||
retlen = write(test_pipe[1], "F\n", 2);
|
||||
tt_int_op(retlen, OP_EQ, 2);
|
||||
retptr = tor_fgets(buf, sizeof(buf), test_stream);
|
||||
tt_int_op(errno, OP_EQ, 0);
|
||||
tt_ptr_op(retptr, OP_EQ, buf);
|
||||
tt_str_op(buf, OP_EQ, "F\n");
|
||||
errno = 0;
|
||||
memset(buf, '\0', sizeof(buf));
|
||||
|
||||
/* Send in a full line and close */
|
||||
retlen = write(test_pipe[1], "GH", 2);
|
||||
tt_int_op(retlen, OP_EQ, 2);
|
||||
retval = close(test_pipe[1]);
|
||||
tt_int_op(retval, OP_EQ, 0);
|
||||
test_pipe[1] = -1;
|
||||
retptr = tor_fgets(buf, sizeof(buf), test_stream);
|
||||
tt_int_op(errno, OP_EQ, 0);
|
||||
tt_ptr_op(retptr, OP_EQ, buf);
|
||||
tt_str_op(buf, OP_EQ, "GH");
|
||||
errno = 0;
|
||||
|
||||
/* Check for EOF */
|
||||
retptr = tor_fgets(buf, sizeof(buf), test_stream);
|
||||
tt_int_op(errno, OP_EQ, 0);
|
||||
tt_ptr_op(retptr, OP_EQ, NULL);
|
||||
retval = feof(test_stream);
|
||||
tt_int_op(retval, OP_NE, 0);
|
||||
errno = 0;
|
||||
|
||||
/* Check that buf is unchanged according to C99 and C11 */
|
||||
tt_str_op(buf, OP_EQ, "GH");
|
||||
memset(buf, '\0', sizeof(buf));
|
||||
|
||||
done:
|
||||
if (test_stream != NULL)
|
||||
fclose(test_stream);
|
||||
if (test_pipe[0] != -1)
|
||||
close(test_pipe[0]);
|
||||
if (test_pipe[1] != -1)
|
||||
close(test_pipe[1]);
|
||||
}
|
||||
|
||||
static void
|
||||
test_util_string_from_pipe(void *ptr)
|
||||
{
|
||||
@ -5839,7 +5729,6 @@ struct testcase_t util_tests[] = {
|
||||
UTIL_TEST(num_cpus, 0),
|
||||
UTIL_TEST_WIN_ONLY(load_win_lib, 0),
|
||||
UTIL_TEST_NO_WIN(exit_status, 0),
|
||||
UTIL_TEST_NO_WIN(fgets_eagain, 0),
|
||||
UTIL_TEST_NO_WIN(string_from_pipe, 0),
|
||||
UTIL_TEST(format_hex_number, 0),
|
||||
UTIL_TEST(format_dec_number, 0),
|
||||
|
Loading…
Reference in New Issue
Block a user