From cade004d7d8cadcbb7f46768b8718518aa81453a Mon Sep 17 00:00:00 2001 From: Arun Date: Tue, 27 Oct 2020 23:40:37 +0530 Subject: [PATCH] Fix file DOWNLOAD strangeness If EXPECTED_HASH is passed to file(DOWNLOAD), it seems to be sending error message and skips few stack frames and returns. This causes package management not to retry failure next time! With this change, hash check is explicitly implemented. --- Arduino/PackageManager/BoardsManager.cmake | 70 ++++++++++++++++++++-- 1 file changed, 65 insertions(+), 5 deletions(-) diff --git a/Arduino/PackageManager/BoardsManager.cmake b/Arduino/PackageManager/BoardsManager.cmake index 331ffab..1aff975 100644 --- a/Arduino/PackageManager/BoardsManager.cmake +++ b/Arduino/PackageManager/BoardsManager.cmake @@ -448,21 +448,52 @@ endfunction() function(_board_mgr_download url _file_path) cmake_parse_arguments(parsed_args "QUIET;REQUIRED" - "RESULT_VARIABLE" "" ${ARGN}) + "RESULT_VARIABLE;EXPECTED_HASH" "" ${ARGN}) if (CMAKE_VERBOSE_MAKEFILE) message(STATUS "Downloading ${url}...") endif() - file(DOWNLOAD "${url}" "${_file_path}" STATUS _status - ${parsed_args_UNPARSED_ARGUMENTS}) - list(GET _status 0 _result) - list(GET _status 1 _result_str) + set(_result 1) + if (parsed_args_EXPECTED_HASH) + string(REPLACE "=" ";" _hash_args "${parsed_args_EXPECTED_HASH}") + list(GET _hash_args 0 _hash_type) + list(GET _hash_args 1 _hash_value) + # Check hash before download + if (EXISTS "${_file_path}") + _board_mgr_check_file_hash("${_hash_type}" "${_hash_value}" + "${_file_path}" _result QUIET) + endif() + endif() + + if (NOT _result EQUAL 0) + file(DOWNLOAD "${url}" "${_file_path}" STATUS _status INACTIVITY_TIMEOUT 5 + ${parsed_args_UNPARSED_ARGUMENTS}) + if (CMAKE_VERBOSE_MAKEFILE) + message("${_file_path} download status:${_status}") + endif() + list(GET _status 0 _result) + list(GET _status 1 _result_str) + else() + if (CMAKE_VERBOSE_MAKEFILE) + message(STATUS "${_file_path} with correct hash exists already!") + endif() + set(_result 0) + endif() + + # Check hash after download + if (_result EQUAL 0 AND parsed_args_EXPECTED_HASH) + _board_mgr_check_file_hash("${_hash_type}" "${_hash_value}" + "${_file_path}" _result) + set(_result_str "Download HASH mismatch") + endif() + if (DEFINED parsed_args_RESULT_VARIABLE) set(${parsed_args_RESULT_VARIABLE} ${_result} PARENT_SCOPE) endif() if (NOT _result EQUAL 0) + file(REMOVE "${_file_path}") if (parsed_args_REQUIRED) error_exit("${_result_str}\n" "Downloading ${url} failed!!!") @@ -559,5 +590,34 @@ macro(_board_mgr_get_pl_tools_list) endmacro() +# Check hash, returns 0 +function(_board_mgr_check_file_hash hash_type expected_hash file_path result_var) + + cmake_parse_arguments(parsed_args "QUIET;REQUIRED" + "" "" ${ARGN}) + + string(TOLOWER "${expected_hash}" expected_hash) + file("${hash_type}" "${file_path}" _actual_hash) + string(TOLOWER "${_actual_hash}" _actual_hash) + if (NOT "${_actual_hash}" STREQUAL "${expected_hash}") + set("${result_var}" 1 PARENT_SCOPE) + if(NOT parsed_args_QUIET) + execute_process(COMMAND ${CMAKE_COMMAND} -E echo + "HASH mismatch for ${file_path}\n" + " expected: [${expected_hash}]\n" + " actual: [${_actual_hash}]") + endif() + + if (parsed_args_REQUIRED) + message(SEND_ERROR "Hash match failed!!!") + elseif(NOT parsed_args_QUIET) + message(WARNING "Hash match failed!!!") + endif() + return() + endif() + + set("${result_var}" 0 PARENT_SCOPE) +endfunction() + #libraries