From f08103b17b071bc1550874652b8110543b53ea19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torbj=C3=B6rn=20SVENSSON?= Date: Sat, 30 Sep 2023 10:55:17 +0200 Subject: [PATCH] Paths starting with "//?/" on Windows are local MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The prefix might be used to support paths longer than MAX_PATH. https://learn.microsoft.com/en-us/windows/win32/fileio/naming-a-file#win32-file-namespaces Signed-off-by: Torbjörn SVENSSON --- .../eclipse/equinox/common/tests/PathTest.java | 17 +++++++++++++++++ .../src/org/eclipse/core/runtime/Path.java | 11 +++++++++-- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/bundles/org.eclipse.equinox.common.tests/src/org/eclipse/equinox/common/tests/PathTest.java b/bundles/org.eclipse.equinox.common.tests/src/org/eclipse/equinox/common/tests/PathTest.java index ebee7e32c7b..13a1c28715b 100644 --- a/bundles/org.eclipse.equinox.common.tests/src/org/eclipse/equinox/common/tests/PathTest.java +++ b/bundles/org.eclipse.equinox.common.tests/src/org/eclipse/equinox/common/tests/PathTest.java @@ -318,6 +318,23 @@ public void testConstructors() { assertEquals("3.0.win", "D:/foo/abc.txt", IPath.forWindows("/D:/foo/abc.txt").toString()); // fullPath = new java.io.File("D:/").toURL().getPath() assertEquals("3.1.win", "D:/", IPath.forWindows("/D:/").toString()); + + final String verylongpath = "C:/dev/verylongpath/00112233445566778899aabbccddeeff/00112233445566778899aabbccddeeff/00112233445566778899aabbccddeeff/" + + "00112233445566778899aabbccddeeff/00112233445566778899aabbccddeeff/00112233445566778899aabbccddeeff/root/lib/gcc/arm-none-eabi/7.3.1/include-fixed"; + anyPath = IPath.forWindows(verylongpath); + assertEquals("3.2.1.win", "C:", anyPath.getDevice()); + assertEquals("3.2.2.win", "dev", anyPath.segment(0)); + assertEquals("3.2.3.win", verylongpath, anyPath.toString()); + + anyPath = IPath.forWindows("//?/" + verylongpath); + assertEquals("3.3.1.win", "C:", anyPath.getDevice()); + assertEquals("3.3.2.win", "dev", anyPath.segment(0)); + assertEquals("3.3.3.win", verylongpath, anyPath.toString()); + + anyPath = IPath.forWindows("\\\\?\\" + verylongpath.replace('/', '\\')); + assertEquals("3.4.1.win", "C:", anyPath.getDevice()); + assertEquals("3.4.2.win", "dev", anyPath.segment(0)); + assertEquals("3.4.3.win", verylongpath, anyPath.toString()); } @Test diff --git a/bundles/org.eclipse.equinox.common/src/org/eclipse/core/runtime/Path.java b/bundles/org.eclipse.equinox.common/src/org/eclipse/core/runtime/Path.java index 8898f7e27e6..dc8930132cf 100644 --- a/bundles/org.eclipse.equinox.common/src/org/eclipse/core/runtime/Path.java +++ b/bundles/org.eclipse.equinox.common/src/org/eclipse/core/runtime/Path.java @@ -310,8 +310,15 @@ private static String backslashToForward(String path, boolean forWindows) { // extract device int i = fullPath.indexOf(DEVICE_SEPARATOR); if (i != -1) { - // remove leading slash from device part to handle output of URL.getFile() - int start = fullPath.charAt(0) == SEPARATOR ? 1 : 0; + int start = 0; + if (fullPath.startsWith("//?/")) { //$NON-NLS-1$ + // Paths prefixed with "//?/" are local paths. For details: + // https://learn.microsoft.com/en-us/windows/win32/fileio/naming-a-file#win32-file-namespaces + start = 4; + } else if (fullPath.charAt(0) == SEPARATOR) { + // remove leading slash from device part to handle output of URL.getFile() + start = 1; + } devicePart = fullPath.substring(start, i + 1); fullPath = fullPath.substring(i + 1, fullPath.length()); }