From 91decc2434d06b17e99cb7075b67f89997f5f08a Mon Sep 17 00:00:00 2001 From: Eric Mehl Date: Mon, 9 Oct 2023 15:33:07 -0400 Subject: [PATCH] FileSystemPath : Work around Windows exFAT bug MSVC's `std::filesystem` has a bug that causes it to fail to retrieve file information on exFAT partitions in versions prior to (roughly) 17.2. That version is the first release after merging a fix from https://github.com/microsoft/STL/pull/2373, but I'm not certain that version has the fix included. Using `std::filesystem::status` instead of `symlink_status()` seems justified because exFAT paritions don't support symlinks. If other partition types are included in the filter for error code 87, this may need to be revisited. --- src/Gaffer/FileSystemPath.cpp | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/src/Gaffer/FileSystemPath.cpp b/src/Gaffer/FileSystemPath.cpp index b9d0fce23f0..0ff833b4842 100644 --- a/src/Gaffer/FileSystemPath.cpp +++ b/src/Gaffer/FileSystemPath.cpp @@ -258,7 +258,28 @@ bool FileSystemPath::isValid( const IECore::Canceller *canceller ) const std::error_code e; - const std::filesystem::file_type t = std::filesystem::symlink_status( std::filesystem::path( this->string() ), e ).type(); + std::filesystem::file_type t = std::filesystem::symlink_status( std::filesystem::path( this->string() ), e ).type(); + +#if _MSC_VER < 1932 + +// Fix MSVC bug preventing `symlink_status()` working with exFAT partitions, and possibly FAT. +// Filtering to error 87 is based on experimentation and backed up by +// https://github.com/microsoft/STL/issues/233. Using `status()` instead of `symlink_status()` +// allows exFAT partitions to be used, and because exFAT does not support symlinks, this +// should be a valid workaround provided filtering to error value `87` doesn't include +// partitions that do support symlinks. +if( + ( + t == std::filesystem::file_type::none || t == std::filesystem::file_type::not_found + ) && e.value() == 87 // "The parameter is incorrect." +) +{ + std::cerr << e.value() << " ( " << e.category().name() << " ) : " << e.message() << "\n"; + t = std::filesystem::status( std::filesystem::path( this->string() ), e ).type(); +} + +#endif + return t != std::filesystem::file_type::none && t != std::filesystem::file_type::not_found; }