1 //===----------------------------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 // UNSUPPORTED: c++03, c++11, c++14 10 // REQUIRES: long_tests 11 // UNSUPPORTED: no-filesystem 12 // UNSUPPORTED: availability-filesystem-missing 13 14 // <filesystem> 15 16 // bool copy_file(const path& from, const path& to); 17 // bool copy_file(const path& from, const path& to, error_code& ec) noexcept; 18 // bool copy_file(const path& from, const path& to, copy_options options); 19 // bool copy_file(const path& from, const path& to, copy_options options, 20 // error_code& ec) noexcept; 21 22 #include <filesystem> 23 #include <cassert> 24 #include <cstdio> 25 #include <string> 26 27 #include "test_macros.h" 28 #include "filesystem_test_helper.h" 29 namespace fs = std::filesystem; 30 using namespace fs; 31 32 // This test is intended to test 'sendfile's 2gb limit for a single call, and 33 // to ensure that libc++ correctly copies files larger than that limit. 34 // However it requires allocating ~5GB of filesystem space. This might not 35 // be acceptable on all systems. 36 static void large_file() { 37 using namespace fs; 38 constexpr std::uintmax_t sendfile_size_limit = 2147479552ull; 39 constexpr std::uintmax_t additional_size = 1024; 40 constexpr std::uintmax_t test_file_size = sendfile_size_limit + additional_size; 41 static_assert(test_file_size > sendfile_size_limit, ""); 42 43 scoped_test_env env; 44 45 // Check that we have more than sufficient room to create the files needed 46 // to perform the test. 47 if (space(env.test_root).available < 3 * test_file_size) { 48 return; 49 } 50 51 // Create a file right at the size limit. The file is full of '\0's. 52 const path source = env.create_file("source", sendfile_size_limit); 53 const std::string additional_data(additional_size, 'x'); 54 // Append known data to the end of the source file. 55 { 56 std::FILE* outf = std::fopen(source.string().c_str(), "a"); 57 assert(outf != nullptr); 58 std::fputs(additional_data.c_str(), outf); 59 std::fclose(outf); 60 } 61 assert(file_size(source) == test_file_size); 62 const path dest = env.make_env_path("dest"); 63 64 std::error_code ec = GetTestEC(); 65 assert(copy_file(source, dest, ec)); 66 assert(!ec); 67 68 assert(is_regular_file(dest)); 69 assert(file_size(dest) == test_file_size); 70 71 // Read the data from the end of the destination file, and ensure it matches 72 // the data at the end of the source file. 73 std::string out_data(additional_size, 'z'); 74 { 75 std::FILE* dest_file = std::fopen(dest.string().c_str(), "r"); 76 assert(dest_file != nullptr); 77 assert(std::fseek(dest_file, sendfile_size_limit, SEEK_SET) == 0); 78 assert(std::fread(&out_data[0], sizeof(out_data[0]), additional_size, dest_file) == additional_size); 79 std::fclose(dest_file); 80 } 81 assert(out_data.size() == additional_data.size()); 82 assert(out_data == additional_data); 83 } 84 85 int main(int, char**) { 86 large_file(); 87 88 return 0; 89 } 90