aboutsummaryrefslogtreecommitdiff
path: root/src/common
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2012-09-17 10:03:11 -0400
committerNick Mathewson <nickm@torproject.org>2012-09-17 10:03:11 -0400
commitc3f526ed64012f64589b926082ff5e542ec7d18d (patch)
treee85837f0956622fb222ab30a82232e37eecba726 /src/common
parent2939cc3ba3afe5ef2c6a273eef18577274e6867b (diff)
parentfaab7881894e55e71c0a19654f3c733c8b0d2920 (diff)
downloadtor-c3f526ed64012f64589b926082ff5e542ec7d18d.tar
tor-c3f526ed64012f64589b926082ff5e542ec7d18d.tar.gz
Merge branch '6044_nm_squashed'
Diffstat (limited to 'src/common')
-rw-r--r--src/common/util.c60
-rw-r--r--src/common/util.h3
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);