[vcpkg] Add non-throwing implementation of write_contents()
MODIFY
include/vcpkg/base/files.h
include/vcpkg/base/files.h
@@ -34,7 +34,7 @@ namespace vcpkg::Files
virtual std::vector<fs::path> get_files_non_recursive(const fs::path& dir) const = 0;
virtual void write_lines(const fs::path& file_path, const std::vector<std::string>& lines) = 0;
- virtual void write_contents(const fs::path& file_path, const std::string& data) = 0;
+ virtual void write_contents(const fs::path& file_path, const std::string& data, std::error_code& ec) = 0;
virtual void rename(const fs::path& oldpath, const fs::path& newpath) = 0;
virtual bool remove(const fs::path& path) = 0;
virtual bool remove(const fs::path& path, std::error_code& ec) = 0;
@@ -51,6 +51,14 @@ namespace vcpkg::Files
fs::copy_options opts,
std::error_code& ec) = 0;
virtual fs::file_status status(const fs::path& path, std::error_code& ec) const = 0;
+
+ inline void write_contents(const fs::path& file_path, const std::string& data)
+ {
+ std::error_code ec;
+ write_contents(file_path, data, ec);
+ Checks::check_exit(
+ VCPKG_LINE_INFO, ec, "error while writing file: %s: %s", file_path.u8string(), ec.message());
+ }
};
Filesystem& get_real_filesystem();

MODIFY
src/vcpkg/base/checks.cpp
src/vcpkg/base/checks.cpp
@@ -10,6 +10,10 @@ namespace vcpkg::Checks
{
[[noreturn]] static void cleanup_and_exit(const int exit_code)
{
+ static std::atomic<bool> have_entered = false;
+ if (have_entered) std::terminate();
+ have_entered = true;
+
const auto elapsed_us = GlobalState::timer.lock()->microseconds();
auto metrics = Metrics::g_metrics.lock();

MODIFY
src/vcpkg/base/files.cpp
src/vcpkg/base/files.cpp
@@ -164,21 +164,30 @@ namespace vcpkg::Files
{
return fs::stdfs::status(path, ec);
}
- virtual void write_contents(const fs::path& file_path, const std::string& data) override
+ virtual void write_contents(const fs::path& file_path, const std::string& data, std::error_code& ec) override
{
+ ec = std::error_code();
+
FILE* f = nullptr;
#if defined(_WIN32)
- auto ec = _wfopen_s(&f, file_path.native().c_str(), L"wb");
+ auto err = _wfopen_s(&f, file_path.native().c_str(), L"wb");
#else
f = fopen(file_path.native().c_str(), "wb");
- int ec = f != nullptr ? 0 : 1;
+ int err = f != nullptr ? 0 : 1;
#endif
- Checks::check_exit(
- VCPKG_LINE_INFO, ec == 0, "Error: Could not open file for writing: %s", file_path.u8string().c_str());
+ if (err != 0)
+ {
+ ec.assign(err, std::system_category());
+ return;
+ }
+
auto count = fwrite(data.data(), sizeof(data[0]), data.size(), f);
fclose(f);
- Checks::check_exit(VCPKG_LINE_INFO, count == data.size());
+ if (count != data.size())
+ {
+ ec = std::make_error_code(std::errc::no_space_on_device);
+ }
}
};

MODIFY
src/vcpkg/metrics.cpp
src/vcpkg/metrics.cpp
@@ -427,8 +427,9 @@ namespace vcpkg::Metrics
}
const fs::path vcpkg_metrics_txt_path = temp_folder_path / ("vcpkg" + generate_random_UUID() + ".txt");
- fs.write_contents(vcpkg_metrics_txt_path, payload);
-
+ std::error_code ec;
+ fs.write_contents(vcpkg_metrics_txt_path, payload, ec);
+ if (ec) return;
const std::string cmd_line = Strings::format("start \"vcpkgmetricsuploader.exe\" \"%s\" \"%s\"",
temp_folder_path_exe.u8string(),
vcpkg_metrics_txt_path.u8string());

MODIFY
src/vcpkg/userconfig.cpp
src/vcpkg/userconfig.cpp
@@ -78,7 +78,8 @@ namespace vcpkg
user_id,
user_time,
user_mac,
- last_completed_survey));
+ last_completed_survey),
+ ec);
}
catch (...)
{

[vcpkg] Add non-throwing implementation of write_contents()