From 9476245dcd886012014608ce3086c79da68f70a3 Mon Sep 17 00:00:00 2001 From: Hanjiang Yu Date: Sun, 23 Mar 2025 10:58:36 +0800 Subject: [PATCH] file(DOWNLOAD): Handle write errors --- Source/cmFileCommand.cxx | 19 +++++++++++-------- .../RunCMake/file-DOWNLOAD/RunCMakeTest.cmake | 7 +++++++ Tests/RunCMake/file-DOWNLOAD/common.cmake | 4 +++- .../file-DOWNLOAD/file-write-error-stdout.txt | 1 + .../file-DOWNLOAD/file-write-error.cmake | 3 +++ 5 files changed, 25 insertions(+), 9 deletions(-) create mode 100644 Tests/RunCMake/file-DOWNLOAD/file-write-error-stdout.txt create mode 100644 Tests/RunCMake/file-DOWNLOAD/file-write-error.cmake diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index e9f234fd01..78dda576e3 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -1703,7 +1703,9 @@ size_t cmWriteToFileCallback(void* ptr, size_t size, size_t nmemb, void* data) cmsys::ofstream* fout = static_cast(data); if (fout) { char const* chPtr = static_cast(ptr); - fout->write(chPtr, realsize); + if (!fout->write(chPtr, realsize)) { + return CURL_WRITEFUNC_ERROR; + } } return realsize; } @@ -2283,6 +2285,14 @@ bool HandleDownloadCommand(std::vector const& args, g_curl.release(); ::curl_easy_cleanup(curl); + // Explicitly close the file so we can check for write errors. + if (!file.empty()) { + fout.close(); + if (!fout) { + res = CURLE_WRITE_ERROR; + } + } + if (!statusVar.empty()) { std::string m = curl_easy_strerror(res); if ((res == CURLE_SSL_CONNECT_ERROR || @@ -2306,13 +2316,6 @@ bool HandleDownloadCommand(std::vector const& args, status.GetMakefile().AddDefinition(logVar, chunkDebug.data()); } - // Explicitly flush/close so we can measure the md5 accurately. - // - if (!file.empty()) { - fout.flush(); - fout.close(); - } - // Verify MD5 sum if requested: // if (hash) { diff --git a/Tests/RunCMake/file-DOWNLOAD/RunCMakeTest.cmake b/Tests/RunCMake/file-DOWNLOAD/RunCMakeTest.cmake index 3fe2090099..11fee2ff28 100644 --- a/Tests/RunCMake/file-DOWNLOAD/RunCMakeTest.cmake +++ b/Tests/RunCMake/file-DOWNLOAD/RunCMakeTest.cmake @@ -23,6 +23,13 @@ run_cmake(no-file) run_cmake(range) run_cmake(SHOW_PROGRESS) +foreach(file IN ITEMS /dev/full /dev/urandom) + if(IS_WRITABLE "${file}") + run_cmake_with_options(file-write-error -Dfile=${file}) + break() + endif() +endforeach() + if(NOT CMake_TEST_NO_NETWORK) run_cmake(bad-hostname) endif() diff --git a/Tests/RunCMake/file-DOWNLOAD/common.cmake b/Tests/RunCMake/file-DOWNLOAD/common.cmake index 6aa2fe60af..d90c4d2bc7 100644 --- a/Tests/RunCMake/file-DOWNLOAD/common.cmake +++ b/Tests/RunCMake/file-DOWNLOAD/common.cmake @@ -2,7 +2,9 @@ if(NOT "${CMAKE_CURRENT_SOURCE_DIR}" MATCHES "^/") set(slash /) endif() set(url "file://${slash}${CMAKE_CURRENT_SOURCE_DIR}/input.png") -set(file ${CMAKE_CURRENT_BINARY_DIR}/output.png) +if (NOT file) + set(file ${CMAKE_CURRENT_BINARY_DIR}/output.png) +endif () function(file_download) file(DOWNLOAD "${url}" diff --git a/Tests/RunCMake/file-DOWNLOAD/file-write-error-stdout.txt b/Tests/RunCMake/file-DOWNLOAD/file-write-error-stdout.txt new file mode 100644 index 0000000000..7d92af2c39 --- /dev/null +++ b/Tests/RunCMake/file-DOWNLOAD/file-write-error-stdout.txt @@ -0,0 +1 @@ +-- status='23;"Failed writing received data to disk/application"' diff --git a/Tests/RunCMake/file-DOWNLOAD/file-write-error.cmake b/Tests/RunCMake/file-DOWNLOAD/file-write-error.cmake new file mode 100644 index 0000000000..1fd931caa6 --- /dev/null +++ b/Tests/RunCMake/file-DOWNLOAD/file-write-error.cmake @@ -0,0 +1,3 @@ +include(common.cmake) + +file_download()