commit 50049df0d4b9ba3654749cfbb111c72e07d54bc5 Author: Nick Mathewson nickm@torproject.org Date: Wed Aug 5 14:01:49 2015 -0400
Add a compat function to check how much disk space is free.
Closes ticket 16734. --- configure.ac | 2 ++ src/common/compat.c | 42 ++++++++++++++++++++++++++++++++++++++++++ src/common/compat.h | 2 ++ src/test/test_util.c | 25 +++++++++++++++++++++++++ 4 files changed, 71 insertions(+)
diff --git a/configure.ac b/configure.ac index d1b7b11..3bb70ed 100644 --- a/configure.ac +++ b/configure.ac @@ -406,6 +406,7 @@ AC_CHECK_FUNCS( rint \ sigaction \ socketpair \ + statvfs \ strlcat \ strlcpy \ strnlen \ @@ -916,6 +917,7 @@ AC_CHECK_HEADERS( sys/resource.h \ sys/select.h \ sys/socket.h \ + sys/statvfs.h \ sys/sysctl.h \ sys/syslimits.h \ sys/time.h \ diff --git a/src/common/compat.c b/src/common/compat.c index 3060817..27a3ece 100644 --- a/src/common/compat.c +++ b/src/common/compat.c @@ -68,6 +68,9 @@ #ifdef HAVE_CRT_EXTERNS_H #include <crt_externs.h> #endif +#ifdef HAVE_SYS_STATVFS_H +#include <sys/statvfs.h> +#endif
#ifdef _WIN32 #include <conio.h> @@ -3374,3 +3377,42 @@ tor_getpass(const char *prompt, char *output, size_t buflen) #endif }
+/** Return the amount of free disk space we have permission to use, in + * bytes. Return -1 if the amount of free space can't be determined. */ +int64_t +tor_get_avail_disk_space(const char *path) +{ +#ifdef HAVE_STATVFS + struct statvfs st; + int r; + memset(&st, 0, sizeof(st)); + + r = statvfs(path, &st); + if (r < 0) + return -1; + + int64_t result = st.f_bavail; + if (st.f_frsize) { + result *= st.f_frsize; + } else if (st.f_bsize) { + result *= st.f_bsize; + } else { + return -1; + } + + return result; +#elif defined(_WIN32) + ULARGE_INTEGER freeBytesAvail; + BOOL ok; + + ok = GetDiskFreeSpaceEx(path, &freeBytesAvail, NULL, NULL); + if (!ok) { + return -1; + } + return (int64_t)freeBytesAvail; +#else + (void)path; + errno = ENOSYS; + return -1; +#endif +} diff --git a/src/common/compat.h b/src/common/compat.h index 3247a59..d3b18eb 100644 --- a/src/common/compat.h +++ b/src/common/compat.h @@ -405,6 +405,8 @@ int tor_fd_setpos(int fd, off_t pos); int tor_fd_seekend(int fd); int tor_ftruncate(int fd);
+int64_t tor_get_avail_disk_space(const char *path); + #ifdef _WIN32 #define PATH_SEPARATOR "\" #else diff --git a/src/test/test_util.c b/src/test/test_util.c index 2bffb17..f8e7661 100644 --- a/src/test/test_util.c +++ b/src/test/test_util.c @@ -4347,6 +4347,30 @@ test_util_writepid(void *arg) tor_free(contents); }
+static void +test_util_get_avail_disk_space(void *arg) +{ + (void) arg; + int64_t val; + + /* No answer for nonexistent directory */ + val = tor_get_avail_disk_space("/akljasdfklsajdklasjkldjsa"); + tt_int_op(val, OP_EQ, -1); + + /* Try the current directory */ + val = tor_get_avail_disk_space("."); + +#if !defined(HAVE_STATVFS) && !defined(_WIN32) + tt_i64_op(val, OP_EQ, -1); /* You don't have an implementation for this */ +#else + tt_i64_op(val, OP_GT, 0); /* You have some space. */ + tt_i64_op(val, OP_LT, ((int64_t)1)<<56); /* You don't have a zebibyte */ +#endif + + done: + ; +} + struct testcase_t util_tests[] = { UTIL_LEGACY(time), UTIL_TEST(parse_http_time, 0), @@ -4414,6 +4438,7 @@ struct testcase_t util_tests[] = { UTIL_TEST(hostname_validation, 0), UTIL_TEST(ipv4_validation, 0), UTIL_TEST(writepid, 0), + UTIL_TEST(get_avail_disk_space, 0), END_OF_TESTCASES };
tor-commits@lists.torproject.org