From: Nikolay Popov Date: Mon, 15 Sep 2025 10:08:30 +0000 (+0300) Subject: llama-run: Fix model download on Windows (#15988) X-Git-Tag: upstream/0.0.6527~49 X-Git-Url: https://git.djapps.eu/?a=commitdiff_plain;h=28c39da7c645185ade5436767929d7ec33006033;p=pkg%2Fggml%2Fsources%2Fllama.cpp 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 --- diff --git a/tools/run/run.cpp b/tools/run/run.cpp index 6fe728c6..772d66c9 100644 --- a/tools/run/run.cpp +++ b/tools/run/run.cpp @@ -407,6 +407,43 @@ class HttpClient { } std::string output_file_partial; + + if (!output_file.empty()) { + output_file_partial = output_file + ".partial"; + } + + if (download(url, headers, output_file_partial, progress, response_str)) { + return 1; + } + + if (!output_file.empty()) { + 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; + } + + ~HttpClient() { + if (chunk) { + curl_slist_free_all(chunk); + } + + if (curl) { + curl_easy_cleanup(curl); + } + } + + private: + 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; @@ -415,8 +452,7 @@ class HttpClient { progress_data data; File out; if (!output_file.empty()) { - output_file_partial = output_file + ".partial"; - if (!out.open(output_file_partial, "ab")) { + if (!out.open(output_file, "ab")) { printe("Failed to open file for writing\n"); return 1; @@ -430,7 +466,7 @@ class HttpClient { } set_write_options(response_str, out); - data.file_size = set_resume_point(output_file_partial); + data.file_size = set_resume_point(output_file); set_progress_options(progress, data); set_headers(headers); CURLcode res = perform(url); @@ -438,27 +474,10 @@ class HttpClient { printe("Fetching resource '%s' failed: %s\n", url.c_str(), curl_easy_strerror(res)); return 1; } - if (!output_file.empty()) { - std::filesystem::rename(output_file_partial, output_file); - } return 0; } - ~HttpClient() { - if (chunk) { - curl_slist_free_all(chunk); - } - - if (curl) { - curl_easy_cleanup(curl); - } - } - - private: - CURL * curl = nullptr; - struct curl_slist * chunk = nullptr; - 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); }