Add support for device UNC paths in canonical() (#171)

This commit is contained in:
Steffen Schümann 2026-07-11 20:40:28 +02:00
parent 730589f53e
commit 58c373188b
3 changed files with 23 additions and 0 deletions

View File

@ -655,6 +655,8 @@ to the expected behavior.
to a host-only UNC path now inserts the missing separator. to a host-only UNC path now inserts the missing separator.
* Fix for [#170](https://github.com/gulrak/filesystem/issues/170), * Fix for [#170](https://github.com/gulrak/filesystem/issues/170),
`lexically_normal()` now preserves IPv6 components in device UNC paths. `lexically_normal()` now preserves IPv6 components in device UNC paths.
* Fix for [#171](https://github.com/gulrak/filesystem/issues/171), `canonical()`
now supports device UNC paths.
* Fix for [#185](https://github.com/gulrak/filesystem/issues/185), * Fix for [#185](https://github.com/gulrak/filesystem/issues/185),
`lexically_normal()` now preserves unresolved parent components in relative `lexically_normal()` now preserves unresolved parent components in relative
paths. paths.

View File

@ -3753,6 +3753,19 @@ GHC_INLINE path canonical(const path& p, std::error_code& ec)
return path(); return path();
} }
path work = p.is_absolute() ? p : absolute(p, ec); path work = p.is_absolute() ? p : absolute(p, ec);
#ifdef GHC_OS_WINDOWS
const path::impl_string_type deviceUncPrefix(GHC_PLATFORM_LITERAL("\\\\.\\UNC\\"));
const path::impl_string_type extendedUncPrefix(GHC_PLATFORM_LITERAL("\\\\?\\UNC\\"));
auto hasPrefix = [&work](const path::impl_string_type& prefix) {
return work._path.length() > prefix.length() &&
std::equal(prefix.begin(), prefix.end(), work._path.begin(), [](path::value_type lhs, path::value_type rhs) {
return std::toupper(static_cast<unsigned char>(lhs)) == std::toupper(static_cast<unsigned char>(rhs));
});
};
if (hasPrefix(deviceUncPrefix) || hasPrefix(extendedUncPrefix)) {
work = path(GHC_PLATFORM_LITERAL("\\\\") + work._path.substr(deviceUncPrefix.length()), path::native_format);
}
#endif
path result; path result;
auto fs = status(work, ec); auto fs = status(work, ec);

View File

@ -2945,6 +2945,14 @@ TEST_CASE("Windows: path namespace handling", "[filesystem][path][fs.path.win.na
auto p2 = fs::canonical(p, ec); auto p2 = fs::canonical(p, ec);
CHECK(!ec); CHECK(!ec);
CHECK(p2 == p); CHECK(p2 == p);
auto p3 = fs::canonical(R"(\\.\UNC\localhost\c$\Windows)", ec);
CHECK(!ec);
CHECK(p3 == p);
auto p4 = fs::canonical(R"(\\?\UNC\localhost\c$\Windows)", ec);
CHECK(!ec);
CHECK(p4 == p);
} }
struct TestInfo struct TestInfo