fix(relinker): accept paths longer than 260 characters on Windows

relinker.exe carried only MinGW's default manifest, so Windows kept MAX_PATH for it even with long paths enabled, and an input under a deep directory failed with 'Cannot open file'. Embed a manifest with longPathAware that keeps asInvoker and the Windows 10 supportedOS entry.
This commit is contained in:
Borooooo committed 2026-10-12 18:50:50 +02:00
1 parent d592d54e11
commit 39bed4b9d7
4 files changed
+71

No files matched your search

+5
View File
@@ -98,6 +98,8 @@ if(BUILD_TESTING AND WIN32)
endif()
if(WIN32)
target_sources(relinker PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/relinker.rc)
set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/relinker.rc PROPERTIES OBJECT_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/relinker.manifest)
target_compile_options(relinker PRIVATE -municode)
target_link_options(relinker PRIVATE -municode)
endif()
@@ -461,6 +463,9 @@ if(BUILD_TESTING)
${CMAKE_CURRENT_SOURCE_DIR}/relinker/tests/test_input_file.py $<TARGET_FILE:relinker>)
add_test(NAME input_nonascii COMMAND ${Python3_EXECUTABLE}
${CMAKE_CURRENT_SOURCE_DIR}/relinker/tests/test_input_nonascii.py $<TARGET_FILE:relinker>)
add_test(NAME long_paths COMMAND ${Python3_EXECUTABLE}
${CMAKE_CURRENT_SOURCE_DIR}/relinker/tests/test_long_paths.py $<TARGET_FILE:relinker>)
set_tests_properties(long_paths PROPERTIES SKIP_RETURN_CODE 77)
add_test(NAME string_table_bounds COMMAND ${Python3_EXECUTABLE}
${CMAKE_CURRENT_SOURCE_DIR}/relinker/tests/test_string_table_bounds.py $<TARGET_FILE:relinker>)
add_test(NAME sce_code_extent COMMAND ${Python3_EXECUTABLE}
+20
View File
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="asInvoker"/>
</requestedPrivileges>
</security>
</trustInfo>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
</application>
</compatibility>
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings>
<longPathAware xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">true</longPathAware>
</windowsSettings>
</application>
</assembly>
+3
View File
@@ -0,0 +1,3 @@
#include <winuser.h>
CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "relinker.manifest"
@@ -0,0 +1,43 @@
"""Convert an input and write outputs whose paths exceed the 260 characters of the Windows MAX_PATH limit."""
import os
from pathlib import Path
import subprocess
import sys
import tempfile
from test_guest_intel_trampolines import main_fixture
def long_paths_enabled():
if os.name != "nt":
return True
import winreg
try:
with winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, r"SYSTEM\CurrentControlSet\Control\FileSystem") as key:
return winreg.QueryValueEx(key, "LongPathsEnabled")[0] == 1
except OSError:
return False
def main():
relinker = Path(sys.argv[1]).resolve()
if not long_paths_enabled():
print("skipped, Windows long paths are disabled: LongPathsEnabled is not 1")
sys.exit(77)
with tempfile.TemporaryDirectory(prefix="anyps5-long-path-") as directory:
work = Path(directory).joinpath(*["long-path-component-" + "x" * 40] * 5)
work.mkdir(parents=True)
source = work / "input.elf"
source.write_bytes(main_fixture())
for options, name in (([], "output.elf"), (["--windows", "--registry"], "output.exe")):
output = work / name
assert len(str(output)) > 260, output
result = subprocess.run([str(relinker), "--skip-sce-module", *options, str(source), str(output)],
capture_output=True, text=True, encoding="utf-8", errors="replace", timeout=20)
assert result.returncode == 0 and output.is_file(), (options, result)
print("Long path tests passed")
if __name__ == "__main__":
main()