aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Karatarakis <alkarata@microsoft.com>2018-06-19 16:59:27 -0700
committerAlexander Karatarakis <alkarata@microsoft.com>2018-06-19 23:07:31 -0700
commit3e76baa163880f59fc344dcff58fd48e526b4a39 (patch)
tree682bfa6297b01df0351151509b96386d817976fa
parent84d65840ab5a36dc095826496a8213ac2404a216 (diff)
downloadvcpkg-3e76baa163880f59fc344dcff58fd48e526b4a39.tar.gz
vcpkg-3e76baa163880f59fc344dcff58fd48e526b4a39.zip
Introduce downloads.h/cpp
-rw-r--r--toolsrc/include/vcpkg/base/downloads.h16
-rw-r--r--toolsrc/src/vcpkg/base/downloads.cpp142
-rw-r--r--toolsrc/src/vcpkg/commands.fetch.cpp138
-rw-r--r--toolsrc/vcpkglib/vcpkglib.vcxproj2
-rw-r--r--toolsrc/vcpkglib/vcpkglib.vcxproj.filters6
5 files changed, 169 insertions, 135 deletions
diff --git a/toolsrc/include/vcpkg/base/downloads.h b/toolsrc/include/vcpkg/base/downloads.h
new file mode 100644
index 000000000..f30e865a6
--- /dev/null
+++ b/toolsrc/include/vcpkg/base/downloads.h
@@ -0,0 +1,16 @@
+#pragma once
+
+#include <vcpkg/base/files.h>
+
+namespace vcpkg::Downloads
+{
+ void verify_downloaded_file_hash(const Files::Filesystem& fs,
+ const std::string& url,
+ const fs::path& path,
+ const std::string& sha512);
+
+ void download_file(vcpkg::Files::Filesystem& fs,
+ const std::string& url,
+ const fs::path& download_path,
+ const std::string& sha512);
+}
diff --git a/toolsrc/src/vcpkg/base/downloads.cpp b/toolsrc/src/vcpkg/base/downloads.cpp
new file mode 100644
index 000000000..a5ee05391
--- /dev/null
+++ b/toolsrc/src/vcpkg/base/downloads.cpp
@@ -0,0 +1,142 @@
+#include "pch.h"
+
+#include <vcpkg/base/downloads.h>
+#include <vcpkg/base/util.h>
+#include <vcpkg/commands.h>
+
+namespace vcpkg::Downloads
+{
+#if defined(_WIN32)
+ static void winhttp_download_file(Files::Filesystem& fs,
+ CStringView target_file_path,
+ CStringView hostname,
+ CStringView url_path)
+ {
+ // Make sure the directories are present, otherwise fopen_s fails
+ const auto dir = fs::path(target_file_path.c_str()).parent_path();
+ std::error_code ec;
+ fs.create_directories(dir, ec);
+ Checks::check_exit(VCPKG_LINE_INFO, !ec, "Could not create directories %s", dir.u8string());
+
+ FILE* f = nullptr;
+ const errno_t err = fopen_s(&f, target_file_path.c_str(), "wb");
+ Checks::check_exit(VCPKG_LINE_INFO,
+ !err,
+ "Could not download https://%s%s. Failed to open file %s. Error code was %s",
+ hostname,
+ url_path,
+ target_file_path,
+ std::to_string(err));
+
+ auto hSession = WinHttpOpen(
+ L"vcpkg/1.0", WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
+ Checks::check_exit(VCPKG_LINE_INFO, hSession, "WinHttpOpen() failed: %d", GetLastError());
+
+ // Use Windows 10 defaults on Windows 7
+ DWORD secure_protocols(WINHTTP_FLAG_SECURE_PROTOCOL_SSL3 | WINHTTP_FLAG_SECURE_PROTOCOL_TLS1 |
+ WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_1 | WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_2);
+ WinHttpSetOption(hSession, WINHTTP_OPTION_SECURE_PROTOCOLS, &secure_protocols, sizeof(secure_protocols));
+
+ // Specify an HTTP server.
+ auto hConnect = WinHttpConnect(hSession, Strings::to_utf16(hostname).c_str(), INTERNET_DEFAULT_HTTPS_PORT, 0);
+ Checks::check_exit(VCPKG_LINE_INFO, hConnect, "WinHttpConnect() failed: %d", GetLastError());
+
+ // Create an HTTP request handle.
+ auto hRequest = WinHttpOpenRequest(hConnect,
+ L"GET",
+ Strings::to_utf16(url_path).c_str(),
+ nullptr,
+ WINHTTP_NO_REFERER,
+ WINHTTP_DEFAULT_ACCEPT_TYPES,
+ WINHTTP_FLAG_SECURE);
+ Checks::check_exit(VCPKG_LINE_INFO, hRequest, "WinHttpOpenRequest() failed: %d", GetLastError());
+
+ // Send a request.
+ auto bResults =
+ WinHttpSendRequest(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0);
+ Checks::check_exit(VCPKG_LINE_INFO, bResults, "WinHttpSendRequest() failed: %d", GetLastError());
+
+ // End the request.
+ bResults = WinHttpReceiveResponse(hRequest, NULL);
+ Checks::check_exit(VCPKG_LINE_INFO, bResults, "WinHttpReceiveResponse() failed: %d", GetLastError());
+
+ std::vector<char> buf;
+
+ size_t total_downloaded_size = 0;
+ DWORD dwSize = 0;
+ do
+ {
+ DWORD downloaded_size = 0;
+ bResults = WinHttpQueryDataAvailable(hRequest, &dwSize);
+ Checks::check_exit(VCPKG_LINE_INFO, bResults, "WinHttpQueryDataAvailable() failed: %d", GetLastError());
+
+ if (buf.size() < dwSize) buf.resize(dwSize * 2);
+
+ bResults = WinHttpReadData(hRequest, (LPVOID)buf.data(), dwSize, &downloaded_size);
+ Checks::check_exit(VCPKG_LINE_INFO, bResults, "WinHttpReadData() failed: %d", GetLastError());
+ fwrite(buf.data(), 1, downloaded_size, f);
+
+ total_downloaded_size += downloaded_size;
+ } while (dwSize > 0);
+
+ WinHttpCloseHandle(hSession);
+ WinHttpCloseHandle(hConnect);
+ WinHttpCloseHandle(hRequest);
+ fflush(f);
+ fclose(f);
+ }
+#endif
+
+ void verify_downloaded_file_hash(const Files::Filesystem& fs,
+ const std::string& url,
+ const fs::path& path,
+ const std::string& sha512)
+ {
+ const std::string actual_hash = Commands::Hash::get_file_hash(fs, path, "SHA512");
+ Checks::check_exit(VCPKG_LINE_INFO,
+ sha512 == actual_hash,
+ "File does not have the expected hash:\n"
+ " url : [ %s ]\n"
+ " File path : [ %s ]\n"
+ " Expected hash : [ %s ]\n"
+ " Actual hash : [ %s ]\n",
+ url,
+ path.u8string(),
+ sha512,
+ actual_hash);
+ }
+
+ void download_file(vcpkg::Files::Filesystem& fs,
+ const std::string& url,
+ const fs::path& download_path,
+ const std::string& sha512)
+ {
+ const std::string download_path_part = download_path.u8string() + ".part";
+ std::error_code ec;
+ fs.remove(download_path, ec);
+ fs.remove(download_path_part, ec);
+#if defined(_WIN32)
+ auto url_no_proto = url.substr(8); // drop https://
+ auto path_begin = Util::find(url_no_proto, '/');
+ std::string hostname(url_no_proto.begin(), path_begin);
+ std::string path(path_begin, url_no_proto.end());
+
+ winhttp_download_file(fs, download_path_part.c_str(), hostname, path);
+#else
+ const auto code = System::cmd_execute(
+ Strings::format(R"(curl -L '%s' --create-dirs --output '%s')", url, download_path_part));
+ Checks::check_exit(VCPKG_LINE_INFO, code == 0, "Could not download %s", url);
+#endif
+
+ verify_downloaded_file_hash(fs, url, download_path_part, sha512);
+ fs.rename(download_path_part, download_path, ec);
+ Checks::check_exit(VCPKG_LINE_INFO,
+ !ec,
+ "Failed to do post-download rename-in-place.\n"
+ "fs.rename(%s, %s, %s)",
+ download_path_part,
+ download_path.u8string(),
+ ec.message());
+ }
+
+}
diff --git a/toolsrc/src/vcpkg/commands.fetch.cpp b/toolsrc/src/vcpkg/commands.fetch.cpp
index 03f7a8a45..0656989c5 100644
--- a/toolsrc/src/vcpkg/commands.fetch.cpp
+++ b/toolsrc/src/vcpkg/commands.fetch.cpp
@@ -1,6 +1,7 @@
#include "pch.h"
#include <vcpkg/base/checks.h>
+#include <vcpkg/base/downloads.h>
#include <vcpkg/base/sortedvector.h>
#include <vcpkg/base/strings.h>
#include <vcpkg/base/system.h>
@@ -335,139 +336,6 @@ namespace vcpkg::Commands::Fetch
ec.message());
}
- static void verify_hash(const Files::Filesystem& fs,
- const std::string& url,
- const fs::path& path,
- const std::string& sha512)
- {
- const std::string actual_hash = Hash::get_file_hash(fs, path, "SHA512");
- Checks::check_exit(VCPKG_LINE_INFO,
- sha512 == actual_hash,
- "File does not have the expected hash:\n"
- " url : [ %s ]\n"
- " File path : [ %s ]\n"
- " Expected hash : [ %s ]\n"
- " Actual hash : [ %s ]\n",
- url,
- path.u8string(),
- sha512,
- actual_hash);
- }
-
-#if defined(_WIN32)
- static void winhttp_download_file(Files::Filesystem& fs,
- CStringView target_file_path,
- CStringView hostname,
- CStringView url_path)
- {
- // Make sure the directories are present, otherwise fopen_s fails
- const auto dir = fs::path(target_file_path.c_str()).parent_path();
- std::error_code ec;
- fs.create_directories(dir, ec);
- Checks::check_exit(VCPKG_LINE_INFO, !ec, "Could not create directories %s", dir.u8string());
-
- FILE* f = nullptr;
- const errno_t err = fopen_s(&f, target_file_path.c_str(), "wb");
- Checks::check_exit(VCPKG_LINE_INFO,
- !err,
- "Could not download https://%s%s. Failed to open file %s. Error code was %s",
- hostname,
- url_path,
- target_file_path,
- std::to_string(err));
-
- auto hSession = WinHttpOpen(
- L"vcpkg/1.0", WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
- Checks::check_exit(VCPKG_LINE_INFO, hSession, "WinHttpOpen() failed: %d", GetLastError());
-
- // Use Windows 10 defaults on Windows 7
- DWORD secure_protocols(WINHTTP_FLAG_SECURE_PROTOCOL_SSL3 | WINHTTP_FLAG_SECURE_PROTOCOL_TLS1 |
- WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_1 | WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_2);
- WinHttpSetOption(hSession, WINHTTP_OPTION_SECURE_PROTOCOLS, &secure_protocols, sizeof(secure_protocols));
-
- // Specify an HTTP server.
- auto hConnect = WinHttpConnect(hSession, Strings::to_utf16(hostname).c_str(), INTERNET_DEFAULT_HTTPS_PORT, 0);
- Checks::check_exit(VCPKG_LINE_INFO, hConnect, "WinHttpConnect() failed: %d", GetLastError());
-
- // Create an HTTP request handle.
- auto hRequest = WinHttpOpenRequest(hConnect,
- L"GET",
- Strings::to_utf16(url_path).c_str(),
- nullptr,
- WINHTTP_NO_REFERER,
- WINHTTP_DEFAULT_ACCEPT_TYPES,
- WINHTTP_FLAG_SECURE);
- Checks::check_exit(VCPKG_LINE_INFO, hRequest, "WinHttpOpenRequest() failed: %d", GetLastError());
-
- // Send a request.
- auto bResults =
- WinHttpSendRequest(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0);
- Checks::check_exit(VCPKG_LINE_INFO, bResults, "WinHttpSendRequest() failed: %d", GetLastError());
-
- // End the request.
- bResults = WinHttpReceiveResponse(hRequest, NULL);
- Checks::check_exit(VCPKG_LINE_INFO, bResults, "WinHttpReceiveResponse() failed: %d", GetLastError());
-
- std::vector<char> buf;
-
- size_t total_downloaded_size = 0;
- DWORD dwSize = 0;
- do
- {
- DWORD downloaded_size = 0;
- bResults = WinHttpQueryDataAvailable(hRequest, &dwSize);
- Checks::check_exit(VCPKG_LINE_INFO, bResults, "WinHttpQueryDataAvailable() failed: %d", GetLastError());
-
- if (buf.size() < dwSize) buf.resize(dwSize * 2);
-
- bResults = WinHttpReadData(hRequest, (LPVOID)buf.data(), dwSize, &downloaded_size);
- Checks::check_exit(VCPKG_LINE_INFO, bResults, "WinHttpReadData() failed: %d", GetLastError());
- fwrite(buf.data(), 1, downloaded_size, f);
-
- total_downloaded_size += downloaded_size;
- } while (dwSize > 0);
-
- WinHttpCloseHandle(hSession);
- WinHttpCloseHandle(hConnect);
- WinHttpCloseHandle(hRequest);
- fflush(f);
- fclose(f);
- }
-#endif
-
- static void download_file(Files::Filesystem& fs,
- const std::string& url,
- const fs::path& download_path,
- const std::string& sha512)
- {
- const std::string download_path_part = download_path.u8string() + ".part";
- std::error_code ec;
- fs.remove(download_path, ec);
- fs.remove(download_path_part, ec);
-#if defined(_WIN32)
- auto url_no_proto = url.substr(8); // drop https://
- auto path_begin = Util::find(url_no_proto, '/');
- std::string hostname(url_no_proto.begin(), path_begin);
- std::string path(path_begin, url_no_proto.end());
-
- winhttp_download_file(fs, download_path_part.c_str(), hostname, path);
-#else
- const auto code = System::cmd_execute(
- Strings::format(R"(curl -L '%s' --create-dirs --output '%s')", url, download_path_part));
- Checks::check_exit(VCPKG_LINE_INFO, code == 0, "Could not download %s", url);
-#endif
-
- verify_hash(fs, url, download_path_part, sha512);
- fs.rename(download_path_part, download_path, ec);
- Checks::check_exit(VCPKG_LINE_INFO,
- !ec,
- "Failed to do post-download rename-in-place.\n"
- "fs.rename(%s, %s, %s)",
- download_path_part,
- download_path.u8string(),
- ec.message());
- }
-
static fs::path fetch_tool(const VcpkgPaths& paths, const std::string& tool_name, const ToolData& tool_data)
{
const std::array<int, 3>& version = tool_data.version;
@@ -488,12 +356,12 @@ namespace vcpkg::Commands::Fetch
if (!fs.exists(tool_data.download_path))
{
System::println("Downloading %s...", tool_name);
- download_file(fs, tool_data.url, tool_data.download_path, tool_data.sha512);
+ Downloads::download_file(fs, tool_data.url, tool_data.download_path, tool_data.sha512);
System::println("Downloading %s... done.", tool_name);
}
else
{
- verify_hash(fs, tool_data.url, tool_data.download_path, tool_data.sha512);
+ Downloads::verify_downloaded_file_hash(fs, tool_data.url, tool_data.download_path, tool_data.sha512);
}
if (tool_data.is_archive)
diff --git a/toolsrc/vcpkglib/vcpkglib.vcxproj b/toolsrc/vcpkglib/vcpkglib.vcxproj
index 871d0c58d..720a1043f 100644
--- a/toolsrc/vcpkglib/vcpkglib.vcxproj
+++ b/toolsrc/vcpkglib/vcpkglib.vcxproj
@@ -141,6 +141,7 @@
<ClInclude Include="..\include\vcpkg\base\chrono.h" />
<ClInclude Include="..\include\vcpkg\base\cofffilereader.h" />
<ClInclude Include="..\include\vcpkg\base\cstringview.h" />
+ <ClInclude Include="..\include\vcpkg\base\downloads.h" />
<ClInclude Include="..\include\vcpkg\base\enums.h" />
<ClInclude Include="..\include\vcpkg\base\expected.h" />
<ClInclude Include="..\include\vcpkg\base\files.h" />
@@ -195,6 +196,7 @@
<ClCompile Include="..\src\vcpkg\base\checks.cpp" />
<ClCompile Include="..\src\vcpkg\base\chrono.cpp" />
<ClCompile Include="..\src\vcpkg\base\cofffilereader.cpp" />
+ <ClCompile Include="..\src\vcpkg\base\downloads.cpp" />
<ClCompile Include="..\src\vcpkg\base\enums.cpp" />
<ClCompile Include="..\src\vcpkg\base\files.cpp" />
<ClCompile Include="..\src\vcpkg\base\lineinfo.cpp" />
diff --git a/toolsrc/vcpkglib/vcpkglib.vcxproj.filters b/toolsrc/vcpkglib/vcpkglib.vcxproj.filters
index 6a23a09b5..299017929 100644
--- a/toolsrc/vcpkglib/vcpkglib.vcxproj.filters
+++ b/toolsrc/vcpkglib/vcpkglib.vcxproj.filters
@@ -201,6 +201,9 @@
<ClCompile Include="..\src\vcpkg\commands.fetch.cpp">
<Filter>Source Files\vcpkg</Filter>
</ClCompile>
+ <ClCompile Include="..\src\vcpkg\base\downloads.cpp">
+ <Filter>Source Files\vcpkg\base</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\include\pch.h">
@@ -347,5 +350,8 @@
<ClInclude Include="..\include\vcpkg\base\stringliteral.h">
<Filter>Header Files\vcpkg\base</Filter>
</ClInclude>
+ <ClInclude Include="..\include\vcpkg\base\downloads.h">
+ <Filter>Header Files\vcpkg\base</Filter>
+ </ClInclude>
</ItemGroup>
</Project> \ No newline at end of file