Repository navigation
fix(kernel): open game files through the extended-length path on Windows when the path is MAX_PATH or longer - #9947
Conversation
|
I reviewed head |
|
Other open pull requests touch the same code. Merging one will break the other, or both implement the same thing. If this one builds on them, list them in Depends on.
Some comparisons could not be completed because a pull request conflicts with the base branch. Review these shared files manually before concluding that there is no overlap.
|
7925fd2 to
97a7c25
Compare
|
Thanks. Added The test found a real bug in the helper: on this toolchain (WinLibs GCC 15.2.0, libstdc++) The branch is force-pushed as two commits: the fix and the test. The test passes here; I ran it on Windows only. I re-ran Samurai Maiden on the final build: no bundle open fails (only AI-assisted: yes. Written with AI assistance and reviewed by me. |
|
The UNC fix and new Windows-only path tests cover the reported cases well. One remaining helper edge case: the first |
|
|
||
| inline std::filesystem::path WindowsExtendedPath(const std::filesystem::path& path) { | ||
| #ifdef _WIN32 | ||
| constexpr std::size_t maxPath = 260; |
There was a problem hiding this comment.
The early return still leaves the short-relative-path case from my previous comment unchanged: relative\\file returns before absolute() is called, even if the current directory makes its resolved path reach MAX_PATH. WindowsExtendedPath.cpp currently tests a relative input whose own length exceeds 260, so it does not exercise that case. Please resolve relative paths before this length decision (or otherwise ensure the resolved path is checked), and add a short relative input under a long current directory as a regression test.
MarcZX10
left a comment
There was a problem hiding this comment.
The exact-head implementation still returns short relative paths before resolving them. A short relative input can resolve past MAX_PATH under a long current directory, while the added test only uses a relative string already longer than the limit. Please resolve/check the relative path before this early return and add the short-relative-under-long-current-directory regression case. Exact-head diff-check and conventions pass; hosted eligibility, conventions, labels and report pass, while product/relinker jobs are skipped. I have not run the Windows-only CTest locally.
|
Additional check on exact head |
|
Agreed, and fixed in a third commit (the branch is pushed, no force needed this time). The helper now resolves a relative path before comparing its length; an absolute path under 260 characters still returns at once, so the common case does no extra work. A path that New case in AI-assisted: yes. Written with AI assistance and reviewed by me. |
MarcZX10
left a comment
There was a problem hiding this comment.
Reviewed exact head b1ab76973a82cfe88193fae36a62f23e4e4289f4. The third commit resolves relative paths before checking the normalized absolute length, preserves the fast path for short absolute paths, and adds the requested short-relative-name under long-current-directory case with cleanup. The reported Windows 11 run passes the updated helper test and repeats the title reproduction. I independently compiled and linked the exact Windows test and helper with MinGW-w64 GCC 12.2 (-std=c++20 -Wall -Wextra -Werror); this host has no Windows runtime, so I did not execute the binary. Exact-head diff-check and conventions pass. Product/relinker CI remains skipped by repository path policy.
| const auto original = std::filesystem::current_path(); | ||
| const std::wstring file = L"file_" + std::wstring(30, L'x'); | ||
| if (original.native().size() + file.size() + 1 < 260) Require(Extend(file) == file); | ||
| const auto root = std::filesystem::temp_directory_path() / L"aps5_extended_path_test"; |
There was a problem hiding this comment.
This test uses a fixed path under the system temp directory and later calls remove_all(root). If aps5_extended_path_test already exists, the test can delete unrelated user data; two concurrent runs can also interfere with one another. Please create a unique, exclusively-created temporary directory for each run and remove only that directory.
MarcZX10
left a comment
There was a problem hiding this comment.
One issue remains in the new regression test: it creates and recursively removes a fixed directory under the system temp path (aps5_extended_path_test). That can delete a pre-existing directory belonging to the user or interfere with a concurrent test run. Please use an exclusively created unique temp directory and clean up only that directory. The short-relative-path fix itself is present; exact-head diff-check/conventions pass, and the Windows test/helper cross-compile and link cleanly (runtime assertions were not run here).
|
For a repository-local pattern, |
|
Fixed in a fourth commit (pushed, no force). The relative-path case now creates its directory with
AI-assisted: yes. Written with AI assistance and reviewed by me. |
1282b3a to
eff20c8
Compare
|
Re-checked on current
I only checked the log for the stall, not the picture. The earlier run on this PR reached the menu. The re-review of the last commit (unique temp directory in the test) is still open if anyone has a moment. AI-assisted: yes. Written with AI assistance and reviewed by me. |
Dismissing a stale review: the requested changes were addressed after it (new head and/or updated description with the asked-for runs) and the merge queue blocks on it. Please request changes again if anything is still open.
|
Rebased onto current I built the rebased head and AI-assisted: yes. Written with AI assistance and reviewed by me. |
eff20c8 to
4cda47b
Compare
|
Windows run of head
So the file open fix works. Three notes:
AI-assisted: yes (Claude Code); results above were run on this machine. |
|
Thanks for running this against main and for the guest-level comparison, that is a more direct check than my unit test. I agree with all three points and pushed a follow-up commit (aa978a8):
I added your cases to the tests: opening and reading a long file and opening a long directory with AI-assisted: yes. Written with AI assistance and reviewed by me. |
|
Re-checked head
One new problem: listing a long directory returns the current directory's entries. The path AI-assisted: yes (Claude Code); results above were run on this machine. |
|
Gruzzberry here: I am opening a small PR that changes the file number (d_fileno) getdirentries reports in DirectoryDescriptor.cpp, next to lines your PR edits. Proposal: yours goes first and mine rebases. Tell me if you would rather go the other way. |
|
Thanks, good catch, and the standalone repro made it easy to confirm. I pushed a follow-up commit (22a7ae7):
I merged the branch onto current
I did not test the long UNC listing ( AI-assisted: yes. Written with AI assistance and reviewed by me. |
|
Thanks for this. The current head doesn't build on Linux: In |
94db793 to
4eac542
Compare
|
@oneandonlydean thanks, fixed in 4eac542. The I checked I also rebased the branch onto main 88e804b to clear the conflict. The only conflict was in AI-assisted: yes. Written with AI assistance and reviewed by me. |
4eac542 to
a5be6b2
Compare
|
Rebased onto current main (head a5be6b2). The only conflict was in AI-assisted: yes. Written with AI assistance and reviewed by me. |
BunnyFl
left a comment
There was a problem hiding this comment.
XairRrR's two points look addressed in 67c3f5e, and here's the Windows run the Linux reviews can't give. The O_NOFOLLOW and O_CREAT|O_EXCL link checks in Open.cpp (is_symlink, GetFileAttributesW, ReadJunction) now use the extended openPath. The APR end-of-file size check in Apr.cpp uses the extended hostPath, with the new longeof case. The UNC branch of WindowsExtendedPath keeps the \server\share root and gives \?\UNC\server\share\... for a long path.
Tested on Windows 11, WinLibs GCC 15.2.0, with this head merged onto current main: 15 of 15 pass, nothing skipped. They are guest_filesystem, guest_directory, guest_directory_entries, the nine guest_apr_read_* cases including guest_apr_read_longeof, long_paths, agc_pipeline_journal_long_paths and agc_shader_disk_cache_long_paths. With main's Apr.cpp, DirectoryDescriptor.cpp, Open.cpp and libkernel CMakeLists.txt (XairRrR's negative-control set), guest_filesystem aborts (0xc0000409).
XairRrR
left a comment
There was a problem hiding this comment.
Re-checked — approved
Both blocking findings from my last review are fixed. Commit 67c3f5e7b9 puts the sceKernelOpen link checks and the APR end-of-file file_size call on the extended path and adds LongNoFollow and guest_apr_read_longeof. Commit a5be6b2720 moves the helper include out of the #ifdef _WIN32 block, so the Linux build works again. The two failures the bot reported come from main, not from this PR.
What changed since my last review
I last reviewed fa00e458e6. Since then:
67c3f5e7b9:OpenNativenow computesopenPathonce and uses it for theO_DIRECTORYstatus check, theO_CREAT|O_EXCLreparse-point check and theO_NOFOLLOWchecks._readFileuses onehostPathfor the stream and forfile_size._fileSizeextends the parent directory before listing it and extends the path in itsis_regular_filefallback. The unreachable#ifdefinLoadis gone. UNC normalization now keeps\\server\shareas the root.- New tests:
LongNoFollowinGuestWindowsDirectoryLinkTypes.cpp,guest_apr_read_longeof, and a\\server\share\..\file.bincase inwindows_extended_path. a5be6b2720: theWindowsExtendedPath.hppinclude inOpen.cppsits above the#ifdef _WIN32block. This fixes the Linux build error reported by oneandonlydean.- Rebases: the branch was rebased onto newer
main. The range-diff shows only context changes in the earlier commits. - Other reviews: BunnyFl approved and reported a Windows run: 15/15 pass, and with
main's production filesguest_filesystemaborts.
What I ran
Head a5be6b2720c0af77b3324523f07af18b8c870793, main 5cb015caaaaf83f8ee431414ee6a457b5b307d49, merged tree 766baa0fe992b51a75c8c6b93fc766ee0297cf94 (Linux, GCC 14.2.0, Release, Ninja).
git diff --check 5cb015caaaaf83f8ee431414ee6a457b5b307d49...a5be6b2720c0af77b3324523f07af18b8c870793
python3 tools/check_conventions.py --base 5cb015caaaaf83f8ee431414ee6a457b5b307d49
ctest --test-dir build --output-on-failure --repeat until-fail:3 \
-R '^(agc_driver_image_sample_lod_clamp_shader_lane|unwrap_self_UnwrapTest_test_new_output_inherits_the_destination_directory_group|guest_filesystem|guest_apr_read_.*)$'
# attempted negative control: Apr.cpp, DirectoryDescriptor.cpp, Open.cpp, libkernel CMakeLists.txt from main
git show 5cb015caaa:<path> > <path>
ninja -C build -j32 -l32 libkernel agc_driver_image_sample_lod_clamp_tests guest_filesystem_tests guest_apr_read_tests
git show 766baa0fe9:<path> > <path>
git status --porcelain
git log --oneline 096c45570f..5cb015caaa -- core/libs/prx/libSceAgcDriver core/shader tools/unwrap_self.py tools/tests/test_unwrap_self.py| Check | Result |
|---|---|
git diff --check |
clean |
check_conventions.py |
All conventions checks passed. |
| Build (script) | configure, build and libs OK |
guest_filesystem, the 7 Linux guest_apr_read_* cases |
pass, 3 repeats each |
agc_driver_image_sample_lod_clamp_shader_lane |
fails every time; comes from main (see below) |
unwrap_self_..._destination_directory_group |
fails (os.chown → EINVAL in the sandbox); comes from main (see below) |
windows_extended_path, guest_windows_directory_link_types, guest_apr_read_longeof |
not built here (Windows-only) |
The two new failures come from main:
- The failure baseline is from
096c45570f, which is older thanmain. Since thenmainmerged4e2a028e43 fix(agc): bind a T# minimum LOD through an S# that holds the LOD at 0(#12980) and new unwrap test cases (#14558). Those are the two failing tests. - On Linux the PR changes nothing at run time:
WindowsExtendedPathreturns its input unchanged when_WIN32is not defined. Every other changed line inApr.cpp,Open.cppandDirectoryDescriptor.cppis inside_WIN32code or goes through that helper. - The unwrap test is a Python test of
tools/, which this PR does not touch. - I tried to confirm the AGC failure by rebuilding with
main's production files, but could not (see Not verified).
AGC failure (same as build.json)
AGC graphics: image_sample_lz through the S# that holds the LOD at 0 with T# MIN_LOD 768 ... thread 0 component 1 is 0.000000, expected 0.062500
Previous findings
- Blocking 1,
sceKernelOpenlink checks on the plain path: Resolved.core/libs/prx/libkernel/File/src/Open.cpp:235-255usesopenPathforstatus, bothGetFileAttributesWcalls,is_symlinkandReadJunction. TheLongNoFollowcase expects0x8002001Ffor a junction pastMAX_PATH. I checked this in source. The Windows run and negative control are BunnyFl's and the author's reports. - Blocking 2, APR end-of-file
file_sizeon the plain path: Resolved.core/libs/prx/libkernel/Apr/src/Apr.cpp:165-188useshostPathfor both the stream andfile_size.guest_apr_read_longeofreads 200 bytes from a 100-byte long-path file and checks the zero fill and the guard bytes. Its Windows result is author-reported. - Non-blocking 1, APR size lookup and stat: Resolved.
Apr.cpp:79andApr.cpp:106extend the path.FillFileStatgoes throughNativeMetadataPath→WindowsNormalizedPath(Open.cpp:120-121), and the debt entry names the size lookup and the end-of-file check. - Non-blocking 2, dead
#ifdefinLoad: Resolved. The non-Windows loop now has only theDirectoryEntryTypeline. - Non-blocking 3, UNC
..under the share: Resolved.WindowsExtendedPath.hpp:20-28normalizes only the part after\\server\share, andwindows_extended_pathhas the\\server\share\..\file.bincase.
New findings
Blocking
None.
Non-blocking
- APR directory listing at the
MAX_PATHboundary (core/libs/prx/libkernel/Apr/src/Apr.cpp:79).- The listing extends
path.parent_path()first and appends\*afterwards. This is the boundary case mashingaan found inListDirectoryEntries, which the PR already fixed there. - For a parent of 258 or 259 characters,
WindowsExtendedPathleaves the parent unchanged and the search pattern reaches 260.FindFirstFileExWthen fails, and an empty size map is cached for that directory. - Results stay correct, because each file then falls back to
is_regular_file+FillFileStaton the extended path. But every file in such a directory pays a separate stat. - Suggested fix:
File::WindowsExtendedPath(path.parent_path() / L"*"), asDirectoryDescriptor.cpp:145does.
- The listing extends
Not verified
- Linux negative control: I did not repeat it. On Linux the helper returns the path unchanged, so a Linux run cannot fail. My previous review showed this.
- AGC failure check: I tried to confirm it with
main's production files, but the sandbox stopped the build: CMake's regeneration fails withOperation not permittedin SDL2'sconfigure_file. That attribution rests on themainhistory and on the Linux no-op argument above. The worktree is back at the merged tree (git status --porcelainis empty), but the build tree'sbuild.ninjais now marked for regeneration. - Windows: nothing was compiled or run on Windows here. The Windows tests and the Windows negative controls are from BunnyFl's and the author's runs.
- Title run: the PPSA04132 reproduction was not run (Windows-only, and this review does not launch titles).
✅ AMD GPU test: passedPR head
Unstable on main (1, these also failed in recent main runs on this machine; not counted against this PR)Failing on main too (12, not counted against this PR)Validation IDs already present on main (4 IDs in 754 tests)Skipped (59)ReproduceAutomated build and test on a contributor's AMD machine; it does not replace upstream CI. A new comment is posted for each new push. Full logs. |
|
Hi klosixgaming-arch, Thanks for moving the Since then, #12560 (merged today) added a shared helper for the same job: Could you rebase onto current
If the helper's rules differ from yours for a case you need (for example its handling of DOS device names and trailing dots or spaces), please say which case, so the difference is settled in one place. |
…ctory listings on Windows Builds on NativeVerbatimPath_nid_no_patch from boykopovar#12560 instead of a second helper: the APR read, size lookup and end-of-file check, the /app0 root, the O_NOFOLLOW symlink check and the directory fallback in open, and directory listings through FindFirstFileExW with a verbatim search pattern.
a5be6b2 to
61546e6
Compare
|
@oneandonlydean done in 61546e6. The branch is now one commit on main 4f41f4c.
I used the helper's default limit (248), as AI-assisted: yes. Written with AI assistance and reviewed by me. |
XairRrR
left a comment
There was a problem hiding this comment.
Re-checked — approved
The branch was rewritten as one commit, 61546e6932, on top of main 4f41f4c375. It removes WindowsExtendedPath.hpp and its test and calls #12560's NativeVerbatimPath_nid_no_patch instead. It keeps the APR, directory-listing, /app0-root and O_NOFOLLOW fixes and their tests. The diff check, the conventions check and the affected Linux tests pass, and I found nothing blocking.
What changed since my last review
I last reviewed a5be6b2720. Since then:
- Rewrite onto the shared helper. oneandonlydean asked for this after #12560 was merged.
File::WindowsExtendedPath/WindowsNormalizedPathand thewindows_extended_pathtest are gone. The debt entry the earlier head added is gone too.mainhas no long-path entry indocs/dev/debt/libkernel.md, so nothing is left stale. Apr.cpp: a new_hostPath(verbatim path, or the plain path if the helper returns an error) is used for the parent listing, theis_regular_filefallback, the stream and the end-of-filefile_size.DirectoryDescriptor.cpp:HostPathdoes the same job.InsideApp0opens the root through it.ListDirectoryEntries(FindFirstFileExW) builds the verbatim pattern from the completedirectory / L"*".Loadstats the directory, its parent and each entry through verbatim paths.OpenDirectoryDescriptorchecksis_directoryon the verbatim path.
Open.cpp: theO_NOFOLLOWis_symlinkcheck usesopenNativeon Windows. The directory fallback after a failed open goes throughNativeMetadataPath.- Tests: these are the same as before:
guest_apr_read_longeof, theLongApp0Root,LongNoFollowandSearchPatternAtMaxPathcases inGuestWindowsDirectoryLinkTypes.cpp, and the long-path open andgetdentschecks inGuestFilesystem.cpp. All of them are Windows-only. - Windows results in the description are author-reported. On this head:
- The APR, link-type, filesystem and directory-entry tests pass.
long_paths,guest_directory,guest_filesystem_errorandagc_pipeline_journal_long_pathswere not conclusive or not run. The author says antivirus blocked them.- The title was not retested.
What I ran
Head 61546e69320d5ecca1851f3c5a9f4298c590e4d1, main 4f41f4c375f5abb487dbd184fbc150f31994d762, merged tree a25d61afe035f9a511cfb1512ab077e7b3bc37ad (Linux, GCC 14.2.0, Release, Ninja).
git diff --check 4f41f4c375f5abb487dbd184fbc150f31994d762...61546e69320d5ecca1851f3c5a9f4298c590e4d1
python3 tools/check_conventions.py --base 4f41f4c375f5abb487dbd184fbc150f31994d762
ctest --test-dir build -j8 --test-load 32 --output-on-failure -R '^(guest_filesystem|guest_apr_read_.*|guest_directory.*)$'
git status --porcelain| Check | Result |
|---|---|
git diff --check |
clean |
check_conventions.py |
All conventions checks passed. |
| Build (script) | configure, build and libs OK |
| Script test run | 0 new failures, 0 timeouts; the 9 known failures also fail on main (baseline is main_sha) |
guest_filesystem, 7 Linux guest_apr_read_*, guest_directory, guest_directory_entries, guest_directory_link_types |
10/10 pass |
Windows-only tests (guest_apr_read_longeof, guest_windows_directory_link_types, the long-path part of guest_filesystem) |
not built here |
Negative control
None on this machine. All new and changed test code is inside #ifdef _WIN32 (TestLongHostPathStat sits in the _WIN32 block of GuestFilesystem.cpp, longeof is only registered on WIN32, and GuestWindowsDirectoryLinkTypes.cpp is Windows-only). On Linux the production change does nothing at run time: NativeVerbatimPath_nid_no_patch returns its input when _WIN32 is not defined (core/libs/prx/libc/include/WindowsVerbatimPath.hpp:257-262), and the rest of the changed code is in _WIN32 branches. So no Linux run can fail with main's production files. The Windows negative controls come from earlier heads: the author's and BunnyFl's runs, against code that was functionally the same. Nobody has repeated them on this head.
Previous findings
- Non-blocking 1, APR directory listing at the
MAX_PATHboundary: Resolved.core/libs/prx/libkernel/Apr/src/Apr.cpp:86still extends the parent before it appends\*. But the shared helper switches to the verbatim form from 248 characters (WindowsMaxDirectoryPathLength,WindowsVerbatimPath.hpp:12,252). So a parent left unprefixed is at most 247 characters, and its\*pattern stays at or below 249, under 260. The boundary case can no longer happen.
The two blocking findings from my earlier review (the link checks in sceKernelOpen, and the APR end-of-file file_size) were resolved at a5be6b2720. The rewrite keeps both fixes:
Open.cpp:243-257usesopenNativefor theGetFileAttributesW,is_symlinkandReadJunctionchecks.Apr.cpp:172uses onehostPathfor the stream and forfile_size.
New findings
Blocking
None.
Non-blocking
- Two copies of the same wrapper.
_hostPath(core/libs/prx/libkernel/Apr/src/Apr.cpp:70-74) andHostPath(core/libs/prx/libkernel/File/src/DirectoryDescriptor.cpp:42-50) both do "verbatim path, or the input on error".Open.cpp:235-237andOpenPlaceholder(DirectoryDescriptor.cpp:271-273) write the same thing inline. This could become one helper next toNativeVerbatimPath_nid_no_patch, in this PR or a follow-up. The#ifdefinHostPathis also unneeded, because the helper already has a non-Windows overload. - The new test cases leak on failure.
LongApp0Root,LongNoFollowandSearchPatternAtMaxPath(core/libs/tests/GuestWindowsDirectoryLinkTypes.cpp) andTestLongEofremove their directories only on the success path.LongApp0Rootalso leaves the/app0alias in place ifTypesthrows. Each run uses a freshsteady_clockname, so a failed run only leaves directories behind in the build tree. A small RAII guard, like the one the earlierwindows_extended_pathtest had, would clean them up. - Checklist format.
Unblocks: PPSA04132has no Game bring-up discussion number. CONTRIBUTING asks for the formUnblocks: PPSA01325 #3232. Please add the discussion, if one exists.
Not verified
- Windows: nothing was compiled or run on Windows here. The Windows results on this head are the author's report and are partial, as the description says.
- Windows negative control: not repeated on this head (see above).
- Title run: the PPSA04132 reproduction was not run. It is Windows-only, and this review does not launch titles.
BunnyFl
left a comment
There was a problem hiding this comment.
Re-approving at 61546e6932, the one-commit rewrite onto main 4f41f4c375. My earlier approval was for a5be6b2720. This head is a new implementation, and I read the whole diff again rather than a delta.
What I read
- The new
_hostPath/HostPathhelpers inApr.cppandDirectoryDescriptor.cppcallNativeVerbatimPath_nid_no_patch(core/libs/prx/libc/include/WindowsVerbatimPath.hpp:241) and keeps the plain path when it returns an error. The helper returns\\?\and\\.\paths unchanged (core/libs/prx/libc/include/WindowsVerbatimPath.hpp:247), soListDirectoryEntriescan pass an already verbatim directory back throughHostPathwithout doubling the prefix. Outside Windows it returns the path as given (core/libs/prx/libc/include/WindowsVerbatimPath.hpp:257-262), so the unguarded_hostPathinApr.cppis a no-op on Linux and macOS. - The verbatim entry paths that
Loadpasses toFillLinkStat/TryFillFileStatare safe:NativeStatPathinNativeStat.cppleaves\\?\paths as they are. InsideApp0only changes how the/app0root is opened. The component comparison against the guest directory is unchanged.- In
Open.cpp, the WindowsO_NOFOLLOWcheck now testsopenNative, the path the open itself uses. The directory fallback stats throughNativeMetadataPath, falling back to the plain path on error, like the metadata paths above it. Non-Windows code is unchanged. - The Windows listing in
Loadthrows on anyFindFirstFileExW/FindNextFileWerror exceptERROR_FILE_NOT_FOUNDandERROR_NO_MORE_FILES, like thedirectory_iteratorloop it replaces.
What I ran (Windows 11, WinLibs GCC 15.2.0, Release, this head merged onto 4f41f4c375): 16 tests (guest_apr_read_* including longeof, guest_filesystem, guest_directory, guest_directory_entries, guest_windows_directory_link_types, long_paths, agc_pipeline_journal_long_paths, agc_shader_disk_cache_long_paths): 16/16 pass.
Negative control: the same tests with Apr.cpp, DirectoryDescriptor.cpp and Open.cpp taken from main: 3 of 16 fail, all in the new cases.
guest_apr_read_longeofguest_filesystem: "Filesystem check failed at line 392 (guest errno 13, Win32 error 3)", the long/long-stat-host/directory open.guest_windows_directory_link_types: line 120, the directory open inTypes().
One limit of this run: the link-type test printed "Symbolic-link cases require Windows developer mode or symbolic-link privilege; junction cases still run". Its symbolic-link cases did not run here; the junction cases did.
✅ AMD GPU test: passedPR head
Unstable on main (3, these also failed in recent main runs on this machine; not counted against this PR)Failing on main too (13, not counted against this PR)Validation IDs already present on main (4 IDs in 767 tests)Skipped (60)ReproduceAutomated build and test on a contributor's AMD machine; it does not replace upstream CI. A new comment is posted for each new push. Full logs. |
What
On Windows,
CreateFileWand the streams built on it refuse an ordinary path of 260 characters (MAX_PATH) or more. #12560 added the sharedNativeVerbatimPath_nid_no_patchand already uses it inopenand the directory open. This PR builds on that helper for the places that still used the plain path:FindFirstFileExWlisting of the parent and theis_regular_filefallback) and the end-of-file checkLoadlists a directory throughFindFirstFileExWwith a verbatim search pattern on Windows and stats the directory, its parent and each entry through the verbatim path.InsideApp0opens the/app0root that way, andOpenDirectoryDescriptorchecks for a directory that way.sceKernelOpen: theO_NOFOLLOWsymlink check and the directory fallback after a failed openSamurai Maiden (PPSA04132, 01.060.000) has asset bundles with long names under
Media/StreamingAssets/aa/PS5/. Under a 116-character runtime folder, every open whose resolved path reached 260 characters failed, and the title stayed dimmed on its logo screen.Tested
Windows 11 (10.0.26200), WinLibs GCC 15.2.0, this head on main
4f41f4c375:guest_apr_read_*cases including the newguest_apr_read_longeof;guest_filesystem;guest_windows_directory_link_types(withLongNoFollow);guest_directory_entries,_buffer,_rewindand_close;agc_shader_disk_cache_long_pathslong_pathsfailed while removing its temporary folder (WinError 32, file in use). Antivirus on this machine was blockingctest.exeat the time, so I couldn't rerun it,guest_directory,guest_filesystem_errororagc_pipeline_journal_long_paths.Open.cpp,Apr.cppandDirectoryDescriptor.cppcompile on Linux (g++ -fsyntax-only). No full Linux build.Checklist
main; no other open PR implements the same functions.mdfiles or images added to the repository