diff options
author | Nick Mathewson <nickm@torproject.org> | 2012-09-17 10:03:11 -0400 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2012-09-17 10:03:11 -0400 |
commit | c3f526ed64012f64589b926082ff5e542ec7d18d (patch) | |
tree | e85837f0956622fb222ab30a82232e37eecba726 /src/common | |
parent | 2939cc3ba3afe5ef2c6a273eef18577274e6867b (diff) | |
parent | faab7881894e55e71c0a19654f3c733c8b0d2920 (diff) | |
download | tor-c3f526ed64012f64589b926082ff5e542ec7d18d.tar tor-c3f526ed64012f64589b926082ff5e542ec7d18d.tar.gz |
Merge branch '6044_nm_squashed'
Diffstat (limited to 'src/common')
-rw-r--r-- | src/common/util.c | 60 | ||||
-rw-r--r-- | src/common/util.h | 3 |
2 files changed, 63 insertions, 0 deletions
diff --git a/src/common/util.c b/src/common/util.c index 5329a0504..4e203e7de 100644 --- a/src/common/util.c +++ b/src/common/util.c @@ -1833,6 +1833,10 @@ file_status(const char *fname) return FN_DIR; else if (st.st_mode & S_IFREG) return FN_FILE; +#ifndef _WIN32 + else if (st.st_mode & S_IFIFO) + return FN_FILE; +#endif else return FN_ERROR; } @@ -2263,6 +2267,46 @@ write_bytes_to_new_file(const char *fname, const char *str, size_t len, (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 * string; return the string on success or NULL on failure. * @@ -2311,6 +2355,22 @@ read_file_to_str(const char *filename, int flags, struct stat *stat_out) 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) return NULL; diff --git a/src/common/util.h b/src/common/util.h index 04812df7c..6667978d1 100644 --- a/src/common/util.h +++ b/src/common/util.h @@ -361,6 +361,9 @@ struct stat; #endif char *read_file_to_str(const char *filename, int flags, struct stat *stat_out) 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, char **key_out, char **value_out); char *expand_filename(const char *filename); |