From 28c39da7c645185ade5436767929d7ec33006033 Mon Sep 17 00:00:00 2001 From: Nikolay Popov <131475237+npopov-vst@users.noreply.github.com> Date: Mon, 15 Sep 2025 13:08:30 +0300 Subject: [PATCH] llama-run: Fix model download on Windows (#15988) * llama-run: Fix model download on Windows * fix SSL error (SSL peer certificate or SSH remote key was not OK) * fix program crash on std::filesystem::rename * llama-run: create a separate method to utilize RAII * llama-run: handle rename exception --- tools/run/run.cpp | 72 +++++++++++++++++++++++++++++++---------------- 1 file changed, 47 insertions(+), 25 deletions(-) diff --git a/tools/run/run.cpp b/tools/run/run.cpp index 6fe728c685..772d66c921 100644 --- a/tools/run/run.cpp +++ b/tools/run/run.cpp @@ -407,39 +407,22 @@ class HttpClient { } std::string output_file_partial; - curl = curl_easy_init(); - if (!curl) { - return 1; - } - progress_data data; - File out; if (!output_file.empty()) { output_file_partial = output_file + ".partial"; - if (!out.open(output_file_partial, "ab")) { - printe("Failed to open file for writing\n"); - - return 1; - } - - if (out.lock()) { - printe("Failed to exclusively lock file\n"); - - return 1; - } } - set_write_options(response_str, out); - data.file_size = set_resume_point(output_file_partial); - set_progress_options(progress, data); - set_headers(headers); - CURLcode res = perform(url); - if (res != CURLE_OK){ - printe("Fetching resource '%s' failed: %s\n", url.c_str(), curl_easy_strerror(res)); + if (download(url, headers, output_file_partial, progress, response_str)) { return 1; } + if (!output_file.empty()) { - std::filesystem::rename(output_file_partial, output_file); + try { + std::filesystem::rename(output_file_partial, output_file); + } catch (const std::filesystem::filesystem_error & e) { + printe("Failed to rename '%s' to '%s': %s\n", output_file_partial.c_str(), output_file.c_str(), e.what()); + return 1; + } } return 0; @@ -459,6 +442,42 @@ class HttpClient { CURL * curl = nullptr; struct curl_slist * chunk = nullptr; + int download(const std::string & url, const std::vector & headers, const std::string & output_file, + const bool progress, std::string * response_str = nullptr) { + curl = curl_easy_init(); + if (!curl) { + return 1; + } + + progress_data data; + File out; + if (!output_file.empty()) { + if (!out.open(output_file, "ab")) { + printe("Failed to open file for writing\n"); + + return 1; + } + + if (out.lock()) { + printe("Failed to exclusively lock file\n"); + + return 1; + } + } + + set_write_options(response_str, out); + data.file_size = set_resume_point(output_file); + set_progress_options(progress, data); + set_headers(headers); + CURLcode res = perform(url); + if (res != CURLE_OK){ + printe("Fetching resource '%s' failed: %s\n", url.c_str(), curl_easy_strerror(res)); + return 1; + } + + return 0; + } + void set_write_options(std::string * response_str, const File & out) { if (response_str) { curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, capture_data); @@ -507,6 +526,9 @@ class HttpClient { curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); curl_easy_setopt(curl, CURLOPT_DEFAULT_PROTOCOL, "https"); curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1L); +#ifdef _WIN32 + curl_easy_setopt(curl, CURLOPT_SSL_OPTIONS, CURLSSLOPT_NATIVE_CA); +#endif return curl_easy_perform(curl); }