diff options
author | Laszlo Csomor <laszlocsomor@google.com> | 2016-12-15 11:16:44 +0000 |
---|---|---|
committer | John Cater <jcater@google.com> | 2016-12-15 20:37:48 +0000 |
commit | aa1614b6a081ea435c536ef2b93c270dd5b071b8 (patch) | |
tree | 64e250114685ca07827c04317e17afb8bc1ea074 /src/main/java/com/google/devtools/build/lib/windows | |
parent | f00cee8a049ee0456f3aab7128ba06d33b7583b3 (diff) |
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
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/windows')
-rw-r--r-- | src/main/java/com/google/devtools/build/lib/windows/WindowsFileOperations.java | 34 |
1 files changed, 33 insertions, 1 deletions
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`. + * + * <p>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. + * + * <p>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. + * + * <p>Returns an UNC path if `path` is longer than `MAX_PATH` (in <windows.h>). 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; } } |