From aa1614b6a081ea435c536ef2b93c270dd5b071b8 Mon Sep 17 00:00:00 2001 From: Laszlo Csomor Date: Thu, 15 Dec 2016 11:16:44 +0000 Subject: Windows, JNI: implement nativeGetLongPath Implement a JNI method that can resolve 8dot3 style paths. This is necessary because we need to be able to compare 8dot3 style paths and long paths [1], and because implementing this correctly in Java seems to be impossible [2]. This change also adds tests for the JNI isJunction implementation. See https://github.com/bazelbuild/bazel/issues/2101 [1] https://github.com/bazelbuild/bazel/issues/2145 [2] https://github.com/bazelbuild/bazel/issues/2145#issuecomment-266766716 -- PiperOrigin-RevId: 142123750 MOS_MIGRATED_REVID=142123750 --- .../build/lib/windows/WindowsFileOperations.java | 34 +++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) (limited to 'src/main/java/com/google/devtools/build/lib/windows') diff --git a/src/main/java/com/google/devtools/build/lib/windows/WindowsFileOperations.java b/src/main/java/com/google/devtools/build/lib/windows/WindowsFileOperations.java index 0eb287e372..d95f9025b0 100644 --- a/src/main/java/com/google/devtools/build/lib/windows/WindowsFileOperations.java +++ b/src/main/java/com/google/devtools/build/lib/windows/WindowsFileOperations.java @@ -30,6 +30,8 @@ public class WindowsFileOperations { static native int nativeIsJunction(String path, String[] error); + static native boolean nativeGetLongPath(String path, String[] result, String[] error); + /** Determines whether `path` is a junction point or directory symlink. */ public static boolean isJunction(String path) throws IOException { WindowsJniLoader.loadJni(); @@ -44,7 +46,37 @@ public class WindowsFileOperations { } } + /** + * Returns the long path associated with the input `path`. + * + *

This method resolves all 8dot3 style components of the path and returns the long format. For + * example, if the input is "C:/progra~1/micros~1" the result may be "C:\Program Files\Microsoft + * Visual Studio 14.0". The returned path is Windows-style in that it uses backslashes, even if + * the input uses forward slashes. + * + *

May return an UNC path if `path` or its resolution is sufficiently long. + * + * @throws IOException if the `path` is not found or some other I/O error occurs + */ + public static String getLongPath(String path) throws IOException { + String[] result = new String[] {null}; + String[] error = new String[] {null}; + if (nativeGetLongPath(asLongPath(path), result, error)) { + return result[0]; + } else { + throw new IOException(error[0]); + } + } + + /** + * Returns a Windows-style path suitable to pass to Widechar Win32 API functions. + * + *

Returns an UNC path if `path` is longer than `MAX_PATH` (in ). If it's shorter or + * is already an UNC path, then this method returns `path` itself. + */ static String asLongPath(String path) { - return "\\\\?\\" + path.replace('/', '\\'); + return path.length() > 260 && !path.startsWith("\\\\?\\") + ? ("\\\\?\\" + path.replace('/', '\\')) + : path; } } -- cgit v1.2.3