diff options
-rw-r--r-- | src/common/compat.c | 17 | ||||
-rw-r--r-- | src/common/compat.h | 1 | ||||
-rw-r--r-- | src/common/log.c | 8 | ||||
-rw-r--r-- | 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 1760684cf7..dcdf78d49f 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 296042fa50..852a432187 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 7c8a48746a..4ddd54fab0 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 cf116effd1..3a1ebb89a8 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 |