mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-12-01 08:03:31 +01:00
Handle FIFOs in read_file_to_str
add read_file_to_str_until_eof which is used by read_file_to_str if the file happens to be a FIFO. change file_status() to return FN_FILE if st_mode matches S_IFIFO (on not-windows) so that init_key_from_file() will read from a FIFO.
This commit is contained in:
parent
99cb9696ac
commit
d64bf286a1
@ -1807,6 +1807,10 @@ file_status(const char *fname)
|
|||||||
return FN_DIR;
|
return FN_DIR;
|
||||||
else if (st.st_mode & S_IFREG)
|
else if (st.st_mode & S_IFREG)
|
||||||
return FN_FILE;
|
return FN_FILE;
|
||||||
|
#ifndef _WIN32
|
||||||
|
else if (st.st_mode & S_IFIFO)
|
||||||
|
return FN_FILE;
|
||||||
|
#endif
|
||||||
else
|
else
|
||||||
return FN_ERROR;
|
return FN_ERROR;
|
||||||
}
|
}
|
||||||
@ -2237,6 +2241,46 @@ write_bytes_to_new_file(const char *fname, const char *str, size_t len,
|
|||||||
(bin?O_BINARY:O_TEXT));
|
(bin?O_BINARY:O_TEXT));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the contents of the open file <b>fd</b> presuming it is a FIFO
|
||||||
|
* (or similar) file descriptor for which the size of the file isn't
|
||||||
|
* known ahead of time. Return NULL on failure, and a NUL-terminated
|
||||||
|
* string on success. On success, set <b>sz_out</b> to the number of
|
||||||
|
* bytes read.
|
||||||
|
*/
|
||||||
|
char *
|
||||||
|
read_file_to_str_until_eof(int fd, size_t max_bytes_to_read, size_t *sz_out)
|
||||||
|
{
|
||||||
|
ssize_t r;
|
||||||
|
size_t pos = 0;
|
||||||
|
char *string = NULL;
|
||||||
|
size_t string_max = 0;
|
||||||
|
|
||||||
|
if (max_bytes_to_read+1 >= SIZE_T_CEILING)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
do {
|
||||||
|
/* XXXX This "add 1K" approach is a little goofy; if we care about
|
||||||
|
* performance here, we should be doubling. But in practice we shouldn't
|
||||||
|
* be using this function on big files anyway. */
|
||||||
|
string_max = pos + 1024;
|
||||||
|
if (string_max > max_bytes_to_read)
|
||||||
|
string_max = max_bytes_to_read + 1;
|
||||||
|
string = tor_realloc(string, string_max);
|
||||||
|
r = read(fd, string + pos, string_max - pos - 1);
|
||||||
|
if (r < 0) {
|
||||||
|
tor_free(string);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
pos += r;
|
||||||
|
} while (r > 0 && pos < max_bytes_to_read);
|
||||||
|
|
||||||
|
*sz_out = pos;
|
||||||
|
string[pos] = '\0';
|
||||||
|
return string;
|
||||||
|
}
|
||||||
|
|
||||||
/** Read the contents of <b>filename</b> into a newly allocated
|
/** Read the contents of <b>filename</b> into a newly allocated
|
||||||
* string; return the string on success or NULL on failure.
|
* string; return the string on success or NULL on failure.
|
||||||
*
|
*
|
||||||
@ -2285,6 +2329,22 @@ read_file_to_str(const char *filename, int flags, struct stat *stat_out)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
|
/** When we detect that we're reading from a FIFO, don't read more than
|
||||||
|
* this many bytes. It's insane overkill for most uses. */
|
||||||
|
#define FIFO_READ_MAX (1024*1024)
|
||||||
|
if (S_ISFIFO(statbuf.st_mode)) {
|
||||||
|
size_t sz = 0;
|
||||||
|
string = read_file_to_str_until_eof(fd, FIFO_READ_MAX, &sz);
|
||||||
|
if (string && stat_out) {
|
||||||
|
statbuf.st_size = sz;
|
||||||
|
memcpy(stat_out, &statbuf, sizeof(struct stat));
|
||||||
|
}
|
||||||
|
close(fd);
|
||||||
|
return string;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if ((uint64_t)(statbuf.st_size)+1 >= SIZE_T_CEILING)
|
if ((uint64_t)(statbuf.st_size)+1 >= SIZE_T_CEILING)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
@ -360,6 +360,9 @@ struct stat;
|
|||||||
#endif
|
#endif
|
||||||
char *read_file_to_str(const char *filename, int flags, struct stat *stat_out)
|
char *read_file_to_str(const char *filename, int flags, struct stat *stat_out)
|
||||||
ATTR_MALLOC;
|
ATTR_MALLOC;
|
||||||
|
char *read_file_to_str_until_eof(int fd, size_t max_bytes_to_read,
|
||||||
|
size_t *sz_out)
|
||||||
|
ATTR_MALLOC;
|
||||||
const char *parse_config_line_from_str(const char *line,
|
const char *parse_config_line_from_str(const char *line,
|
||||||
char **key_out, char **value_out);
|
char **key_out, char **value_out);
|
||||||
char *expand_filename(const char *filename);
|
char *expand_filename(const char *filename);
|
||||||
|
@ -18,6 +18,117 @@
|
|||||||
#include <tchar.h>
|
#include <tchar.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_util_read_file_fifo_tiny_limit(void *arg)
|
||||||
|
{
|
||||||
|
#ifndef _WIN32
|
||||||
|
char *fifo_name = NULL;
|
||||||
|
char *str = NULL;
|
||||||
|
int fd = -1;
|
||||||
|
int read_fd = -1;
|
||||||
|
size_t sz;
|
||||||
|
(void)arg;
|
||||||
|
|
||||||
|
fifo_name = tor_strdup(get_fname("tor_test_fifo_tiny"));
|
||||||
|
fd = open(fifo_name, O_WRONLY | O_CREAT, 0600);
|
||||||
|
test_neq(fd, -1);
|
||||||
|
test_eq(write(fd, "short", 6), 6);
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
// purposely set limit shorter than what we wrote to the FIFO to
|
||||||
|
// test the maximum, and that it puts the NUL in the right spot
|
||||||
|
|
||||||
|
read_fd = open(fifo_name, O_RDONLY);
|
||||||
|
str = read_file_to_str_until_eof(read_fd, 4, &sz);
|
||||||
|
close(read_fd);
|
||||||
|
|
||||||
|
test_eq(str[0], 's');
|
||||||
|
test_eq(str[1], 'h');
|
||||||
|
test_eq(str[2], 'o');
|
||||||
|
test_eq(str[3], 'r');
|
||||||
|
test_eq(str[4], '\0');
|
||||||
|
|
||||||
|
done:
|
||||||
|
unlink(fifo_name);
|
||||||
|
tor_free(fifo_name);
|
||||||
|
tor_free(str);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_util_read_file_fifo_two_loops(void *arg)
|
||||||
|
{
|
||||||
|
#ifndef _WIN32
|
||||||
|
char *fifo_name = NULL;
|
||||||
|
char *str = NULL;
|
||||||
|
char data[2048];
|
||||||
|
int i = 0;
|
||||||
|
int fd = -1;
|
||||||
|
int read_fd = -1;
|
||||||
|
size_t sz;
|
||||||
|
(void)arg;
|
||||||
|
|
||||||
|
while (i < 2048) {
|
||||||
|
data[i] = (char)(i & 0xff);
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
|
||||||
|
// write more than 1024 bytes to the FIFO to test two passes through
|
||||||
|
// the loop in the method; if the re-alloc size is changed this
|
||||||
|
// should be updated as well.
|
||||||
|
|
||||||
|
fifo_name = tor_strdup(get_fname("tor_fifo_test_2k"));
|
||||||
|
fd = open(fifo_name, O_WRONLY | O_CREAT, 0600);
|
||||||
|
test_neq(fd, -1);
|
||||||
|
test_eq(write(fd, data, 2048), 2048);
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
read_fd = open(fifo_name, O_RDONLY);
|
||||||
|
str = read_file_to_str_until_eof(read_fd, 1024*1024, &sz);
|
||||||
|
close(read_fd);
|
||||||
|
|
||||||
|
for (i = 0; i < 2048; ++i) {
|
||||||
|
test_eq(str[i], (char)(i & 0xff));
|
||||||
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
unlink(fifo_name);
|
||||||
|
tor_free(fifo_name);
|
||||||
|
tor_free(str);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_util_read_file_fifo_zero_bytes(void *arg)
|
||||||
|
{
|
||||||
|
#ifndef _WIN32
|
||||||
|
char *fifo_name = NULL;
|
||||||
|
char *str = NULL;
|
||||||
|
int fd = -1;
|
||||||
|
int read_fd = -1;
|
||||||
|
size_t sz;
|
||||||
|
(void)arg;
|
||||||
|
|
||||||
|
fifo_name = tor_strdup(get_fname("tor_fifo_test_zero_bytes"));
|
||||||
|
// zero-byte fifo
|
||||||
|
fd = open(fifo_name, O_WRONLY | O_CREAT, 0600);
|
||||||
|
test_neq(fd, -1);
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
read_fd = open(fifo_name, O_RDONLY);
|
||||||
|
str = read_file_to_str_until_eof(read_fd, 1024, &sz);
|
||||||
|
close(read_fd);
|
||||||
|
|
||||||
|
test_neq(str, NULL);
|
||||||
|
test_eq(str[0], '\0');
|
||||||
|
|
||||||
|
done:
|
||||||
|
unlink(fifo_name);
|
||||||
|
tor_free(fifo_name);
|
||||||
|
tor_free(str);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
test_util_time(void)
|
test_util_time(void)
|
||||||
{
|
{
|
||||||
@ -3191,6 +3302,9 @@ struct testcase_t util_tests[] = {
|
|||||||
UTIL_TEST(envnames, 0),
|
UTIL_TEST(envnames, 0),
|
||||||
UTIL_TEST(make_environment, 0),
|
UTIL_TEST(make_environment, 0),
|
||||||
UTIL_TEST(set_env_var_in_sl, 0),
|
UTIL_TEST(set_env_var_in_sl, 0),
|
||||||
|
UTIL_TEST(read_file_fifo_tiny_limit, 0),
|
||||||
|
UTIL_TEST(read_file_fifo_two_loops, 0),
|
||||||
|
UTIL_TEST(read_file_fifo_zero_bytes, 0),
|
||||||
END_OF_TESTCASES
|
END_OF_TESTCASES
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user