[tor-commits] [tor/master] Add a tor_ftruncate to replace ftruncate.

nickm at torproject.org nickm at torproject.org
Wed Jul 16 12:01:46 UTC 2014


commit 867f5e6a7602fe5cf54686aa04995eaabaea4c80
Author: Nick Mathewson <nickm at torproject.org>
Date:   Wed Jul 16 13:58:55 2014 +0200

    Add a tor_ftruncate to replace ftruncate.
    
    (Windows doesn't have ftruncate, and some ftruncates do not move the
    file pointer to the start of the file.)
---
 src/common/compat.c  |   17 +++++++++++++++++
 src/common/compat.h  |    1 +
 src/common/log.c     |    8 ++++++--
 src/test/test_util.c |   49 +++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 73 insertions(+), 2 deletions(-)

diff --git a/src/common/compat.c b/src/common/compat.c
index 1760684..dcdf78d 100644
--- a/src/common/compat.c
+++ b/src/common/compat.c
@@ -1004,6 +1004,23 @@ tor_fd_setpos(int fd, off_t pos)
 #endif
 }
 
+/** Replacement for ftruncate(fd, 0): move to the front of the file and remove
+ * all the rest of the file. Return -1 on error, 0 on success. */
+int
+tor_ftruncate(int fd)
+{
+  /* Rumor has it that some versions of ftruncate do not move the file pointer.
+   */
+  if (tor_fd_setpos(fd, 0) < 0)
+    return -1;
+
+#ifdef _WIN32
+  return _chsize(fd, 0);
+#else
+  return ftruncate(fd, 0);
+#endif
+}
+
 #undef DEBUG_SOCKET_COUNTING
 #ifdef DEBUG_SOCKET_COUNTING
 /** A bitarray of all fds that should be passed to tor_socket_close(). Only
diff --git a/src/common/compat.h b/src/common/compat.h
index 296042f..852a432 100644
--- a/src/common/compat.h
+++ b/src/common/compat.h
@@ -408,6 +408,7 @@ void tor_lockfile_unlock(tor_lockfile_t *lockfile);
 off_t tor_fd_getpos(int fd);
 int tor_fd_setpos(int fd, off_t pos);
 int tor_fd_seekend(int fd);
+int tor_ftruncate(int fd);
 
 #ifdef _WIN32
 #define PATH_SEPARATOR "\\"
diff --git a/src/common/log.c b/src/common/log.c
index 7c8a487..4ddd54f 100644
--- a/src/common/log.c
+++ b/src/common/log.c
@@ -1305,6 +1305,10 @@ switch_logs_debug(void)
 void
 truncate_logs(void)
 {
-  for (logfile_t *lf = logfiles; lf; lf = lf->next)
-    ftruncate(lf->fd, 0);
+  for (logfile_t *lf = logfiles; lf; lf = lf->next) {
+    if (lf->fd >= 0) {
+      tor_ftruncate(lf->fd);
+    }
+  }
 }
+
diff --git a/src/test/test_util.c b/src/test/test_util.c
index cf116ef..3a1ebb8 100644
--- a/src/test/test_util.c
+++ b/src/test/test_util.c
@@ -2385,6 +2385,54 @@ test_util_parent_dir(void *ptr)
   tor_free(cp);
 }
 
+static void
+test_util_ftruncate(void *ptr)
+{
+  char *buf = NULL;
+  const char *fname;
+  int fd = -1;
+  const char *message = "Hello world";
+  const char *message2 = "Hola mundo";
+  struct stat st;
+
+  (void) ptr;
+
+  fname = get_fname("ftruncate");
+
+  fd = tor_open_cloexec(fname, O_WRONLY|O_CREAT, 0600);
+  tt_int_op(fd, >=, 0);
+
+  /* Make the file be there. */
+  tt_int_op(strlen(message), ==, write_all(fd, message, strlen(message), 0));
+  tt_int_op(tor_fd_getpos(fd), ==, strlen(message));
+  tt_int_op(0, ==, fstat(fd, &st));
+  tt_int_op(st.st_size, ==, strlen(message));
+
+  /* Truncate and see if it got truncated */
+  tt_int_op(0, ==, tor_ftruncate(fd));
+  tt_int_op(tor_fd_getpos(fd), ==, 0);
+  tt_int_op(0, ==, fstat(fd, &st));
+  tt_int_op(st.st_size, ==, 0);
+
+  /* Replace, and see if it got replaced */
+  tt_int_op(strlen(message2), ==,
+            write_all(fd, message2, strlen(message2), 0));
+  tt_int_op(tor_fd_getpos(fd), ==, strlen(message2));
+  tt_int_op(0, ==, fstat(fd, &st));
+  tt_int_op(st.st_size, ==, strlen(message2));
+
+  close(fd);
+  fd = -1;
+
+  buf = read_file_to_str(fname, 0, NULL);
+  tt_str_op(message2, ==, buf);
+
+ done:
+  if (fd >= 0)
+    close(fd);
+  tor_free(buf);
+}
+
 #ifdef _WIN32
 static void
 test_util_load_win_lib(void *ptr)
@@ -3798,6 +3846,7 @@ struct testcase_t util_tests[] = {
   UTIL_TEST(asprintf, 0),
   UTIL_TEST(listdir, 0),
   UTIL_TEST(parent_dir, 0),
+  UTIL_TEST(ftruncate, 0),
 #ifdef _WIN32
   UTIL_TEST(load_win_lib, 0),
 #endif





More information about the tor-commits mailing list