Properly use error_code in vcpkg_remove_all_impl on Windows.
Reported by here:
Drive by remove lots and lots of calls to operator path& on directory_entry.
MODIFY
src/vcpkg/base/files.cpp
src/vcpkg/base/files.cpp
@@ -402,12 +402,12 @@ namespace
std::error_code ec;
Path failure_point;
- bool check_ec(const std::error_code& ec_arg, const stdfs::directory_entry& current_entry)
+ bool check_ec(const std::error_code& ec_arg, const stdfs::path& current_entry_path)
{
if (ec_arg)
{
ec = ec_arg;
- failure_point = from_stdfs_path(current_entry.path());
+ failure_point = from_stdfs_path(current_entry_path);
return true;
}
@@ -440,6 +440,7 @@ namespace
// Custom implementation of stdfs::remove_all intended to be resilient to transient issues
void vcpkg_remove_all_impl(const stdfs::directory_entry& current_entry, RemoveAllErrorInfo& err)
{
+ const auto& current_entry_path = current_entry.path();
std::error_code ec;
const auto path_status = current_entry.symlink_status(ec);
if (path_status.type() == stdfs::file_type::not_found)
@@ -447,35 +448,50 @@ namespace
return;
}
- if (err.check_ec(ec, current_entry))
+ if (err.check_ec(ec, current_entry_path))
{
return;
}
if ((path_status.permissions() & stdfs::perms::owner_write) != stdfs::perms::owner_write)
{
- remove_file_attribute_readonly(current_entry, ec);
- if (err.check_ec(ec, current_entry)) return;
+ remove_file_attribute_readonly(current_entry_path, ec);
+ if (err.check_ec(ec, current_entry_path)) return;
}
if (stdfs::is_directory(path_status))
{
- for (const auto& entry : stdfs::directory_iterator(current_entry.path()))
+ stdfs::directory_iterator last;
+ for (stdfs::directory_iterator first(current_entry_path, ec);; first.increment(ec))
{
- vcpkg_remove_all_impl(entry, err);
- if (err.ec) return;
+ if (err.check_ec(ec, current_entry_path))
+ {
+ return;
}
- if (!RemoveDirectoryW(current_entry.path().c_str()))
+
+ if (first == last)
{
- ec.assign(GetLastError(), std::system_category());
+ if (RemoveDirectoryW(current_entry_path.c_str()))
+ {
+ ec.clear();
+ return;
}
+
+ ec.assign(GetLastError(), std::system_category());
+ err.failure_point = from_stdfs_path(current_entry_path);
+ return;
}
- else
+
+ vcpkg_remove_all_impl(*first, err);
+ if (err.check_ec(ec, current_entry_path))
{
- stdfs::remove(current_entry.path(), ec);
+ return;
+ }
+ }
}
- err.check_ec(ec, current_entry);
+ stdfs::remove(current_entry_path, ec);
+ err.check_ec(ec, current_entry_path);
}
void vcpkg_remove_all(const stdfs::directory_entry& current_entry, std::error_code& ec, Path& failure_point)

Properly use error_code in vcpkg_remove_all_impl on Windows. (#361)

Reported by @JackBoosY here: https://github.com/microsoft/vcpkg/issues/21905#issuecomment-1039910552

Drive by remove lots and lots of calls to operator path& on directory_entry.