Skip to content

Mod paths: query and create extended paths through the Windows API - #286

Open
pogoflow wants to merge 1 commit into
RetroPortingToolKit:mainfrom
pogoflow:fix/mingw-mod-paths
Open

pogoflow wants to merge 1 commit into
RetroPortingToolKit:mainfrom
pogoflow:fix/mingw-mod-paths

Conversation

@pogoflow

Copy link
Copy Markdown
Contributor

Since 26e75c4 (#282) the mod runtime hands \\?\ paths to std::filesystem. With the MSYS2 mingw64 toolchain from the README (GCC 16.2 here), libstdc++'s status calls go through the CRT's stat, which doesn't accept extended paths:

call on a \\?\ path result on mingw64
create_directories EINVAL, also when the directory exists
is_directory, is_regular_file, exists false (ENOENT)
remove false, no error, nothing removed
create_directory, rename, ifstream/ofstream work

So on Windows scan() stops at "cannot create mods directory: Invalid argument", the host prints mods: unavailable, and run_c_tests.sh fails in mod_presentation_only_test. long_path_test fails in its own fixture setup (create_directories(fixture_io(...))).

Change

  • ModPaths gets kind, exists, is_directory, is_regular_file, is_symlink, create_directories and remove. On Windows they use GetFileAttributesW, CreateDirectoryW, DeleteFileW and RemoveDirectoryW on the extended path; elsewhere they're the std::filesystem calls. create_directories walks the plain absolute path and creates each missing level through its extended form.
  • mod_runtime.cpp uses them where it passed for_io(...) to a status call, create_directories or remove. rename and the streams stay as they are.
  • long_path_test uses them for its fixture (creating directories, checking, the payload removal and cleanup).
  • The relative-input case now runs from the fixture root. above.lexically_relative(fs::current_path()) returned an empty path when the caller's directory spelled the drive letter c: and the fixture C: (Windows keeps whatever spelling the caller used), so the case tested an empty path, and whether it passed depended on the caller's directory.

Testing

On Windows 11, MSYS2 mingw64 GCC 16.2:

  • Before: mod_presentation_only_test fails with "cannot create mods directory: Invalid argument"; long_path_test fails with "filesystem error: cannot create directories: Invalid argument".
  • After: both pass, long_path_test with the working directory spelled C:\… and c:\….

I haven't built it with MSVC or on Linux/macOS. Off Windows the helpers are the plain std::filesystem calls.

Since 26e75c4 the mod runtime passes \\?\ paths to std::filesystem. With
the documented MSYS2 mingw64 toolchain (GCC 16.2) the status calls go
through the CRT's stat, which rejects extended paths: create_directories
fails with EINVAL, is_directory, is_regular_file and exists report
nothing there, and remove reports nothing removed. The runtime then
fails at "cannot create mods directory" and the host runs without mods;
mod_presentation_only_test and long_path_test fail in run_c_tests.sh.

ModPaths now has kind/exists/is_directory/is_regular_file/is_symlink,
create_directories and remove, which use GetFileAttributesW,
CreateDirectoryW, DeleteFileW and RemoveDirectoryW on Windows and the
std::filesystem calls elsewhere. The runtime and the long-path fixture
use them; rename and the file streams keep working with extended paths.

The relative-input case of long_path_test now runs from the fixture root:
lexically_relative(current_path()) returned an empty path when the
caller's directory spelled the drive letter "c:" and the fixture "C:".
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant