From 5d8423a8d1d03890fc8afaa2c1cc01d70ec4a628 Mon Sep 17 00:00:00 2001 From: Dan Albert Date: Tue, 15 Jan 2019 19:14:15 +0000 Subject: Add large file support to create_file for 32-bit. Summary: The tests need to create files larger than 2GB, but size_t is 32-bit on a 32-bit system. Make use of explicit off64_t APIs so we can still use a default off_t for the tests while enabling 64-bit file offsets for create_file. Reviewers: mclow.lists, EricWF Reviewed By: EricWF Subscribers: christof, ldionne, libcxx-commits Differential Revision: https://reviews.llvm.org/D56619 --- libcxx/test/support/filesystem_test_helper.hpp | 46 +++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 5 deletions(-) (limited to 'libcxx') diff --git a/libcxx/test/support/filesystem_test_helper.hpp b/libcxx/test/support/filesystem_test_helper.hpp index f027928700b..467abd5fc67 100644 --- a/libcxx/test/support/filesystem_test_helper.hpp +++ b/libcxx/test/support/filesystem_test_helper.hpp @@ -2,6 +2,9 @@ #define FILESYSTEM_TEST_HELPER_HPP #include "filesystem_include.hpp" + +#include // for ftruncate + #include #include // for printf #include @@ -147,13 +150,46 @@ struct scoped_test_env return raw; } - std::string create_file(std::string filename, std::size_t size = 0) { + // Purposefully using a size potentially larger than off_t here so we can + // test the behavior of libc++fs when it is built with _FILE_OFFSET_BITS=64 + // but the caller is not (std::filesystem also uses uintmax_t rather than + // off_t). On a 32-bit system this allows us to create a file larger than + // 2GB. + std::string create_file(std::string filename, uintmax_t size = 0) { +#if defined(__LP64__) + auto large_file_fopen = fopen; + auto large_file_ftruncate = ftruncate; + using large_file_offset_t = off_t; +#else + auto large_file_fopen = fopen64; + auto large_file_ftruncate = ftruncate64; + using large_file_offset_t = off64_t; +#endif + filename = sanitize_path(std::move(filename)); - std::string out_str(size, 'a'); - { - std::ofstream out(filename.c_str()); - out << out_str; + + if (size > std::numeric_limits::max()) { + fprintf(stderr, "create_file(%s, %ju) too large\n", + filename.c_str(), size); + abort(); } + + FILE* file = large_file_fopen(filename.c_str(), "we"); + if (file == nullptr) { + fprintf(stderr, "fopen %s failed: %s\n", filename.c_str(), + strerror(errno)); + abort(); + } + + if (large_file_ftruncate( + fileno(file), static_cast(size)) == -1) { + fprintf(stderr, "ftruncate %s %ju failed: %s\n", filename.c_str(), + size, strerror(errno)); + fclose(file); + abort(); + } + + fclose(file); return filename; } -- cgit v1.2.3