8003887: File.getCanonicalFile() does not resolve symlinks on MS Windows

Reviewed-by: alanb
This commit is contained in:
Brian Burkhalter 2024-09-05 15:03:54 +00:00
parent b389bb4567
commit 042053c3a8
3 changed files with 127 additions and 26 deletions

View file

@ -490,12 +490,26 @@ final class WinNTFileSystem extends FileSystem {
return path;
return "" + ((char) (c-32)) + ':' + '\\';
}
return canonicalize0(path);
String canonicalPath = canonicalize0(path);
String finalPath = null;
try {
finalPath = getFinalPath(canonicalPath);
} catch (IOException ignored) {
finalPath = canonicalPath;
}
return finalPath;
}
private native String canonicalize0(String path)
throws IOException;
private String getFinalPath(String path) throws IOException {
return getFinalPath0(path);
}
private native String getFinalPath0(String path)
throws IOException;
/* -- Attribute accessors -- */

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -46,31 +46,15 @@ static struct {
jfieldID path;
} ids;
/**
* GetFinalPathNameByHandle is available on Windows Vista and newer
*/
typedef BOOL (WINAPI* GetFinalPathNameByHandleProc) (HANDLE, LPWSTR, DWORD, DWORD);
static GetFinalPathNameByHandleProc GetFinalPathNameByHandle_func;
JNIEXPORT void JNICALL
Java_java_io_WinNTFileSystem_initIDs(JNIEnv *env, jclass cls)
{
HMODULE handle;
jclass fileClass;
fileClass = (*env)->FindClass(env, "java/io/File");
CHECK_NULL(fileClass);
ids.path = (*env)->GetFieldID(env, fileClass, "path", "Ljava/lang/String;");
CHECK_NULL(ids.path);
// GetFinalPathNameByHandle requires Windows Vista or newer
if (GetModuleHandleExW((GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT),
(LPCWSTR)&CreateFileW, &handle) != 0)
{
GetFinalPathNameByHandle_func = (GetFinalPathNameByHandleProc)
GetProcAddress(handle, "GetFinalPathNameByHandleW");
}
}
/* -- Path operations -- */
@ -88,10 +72,6 @@ static WCHAR* getFinalPath(JNIEnv *env, const WCHAR *path)
WCHAR *result;
DWORD error;
/* Need Windows Vista or newer to get the final path */
if (GetFinalPathNameByHandle_func == NULL)
return NULL;
h = CreateFileW(path,
FILE_READ_ATTRIBUTES,
FILE_SHARE_DELETE |
@ -109,13 +89,13 @@ static WCHAR* getFinalPath(JNIEnv *env, const WCHAR *path)
*/
result = (WCHAR*)malloc(MAX_PATH * sizeof(WCHAR));
if (result != NULL) {
DWORD len = (*GetFinalPathNameByHandle_func)(h, result, MAX_PATH, 0);
DWORD len = GetFinalPathNameByHandleW(h, result, MAX_PATH, 0);
if (len >= MAX_PATH) {
/* retry with a buffer of the right size */
WCHAR* newResult = (WCHAR*)realloc(result, (len+1) * sizeof(WCHAR));
if (newResult != NULL) {
result = newResult;
len = (*GetFinalPathNameByHandle_func)(h, result, len, 0);
len = GetFinalPathNameByHandleW(h, result, len, 0);
} else {
len = 0;
JNU_ThrowOutOfMemoryError(env, "native memory allocation failed");
@ -351,6 +331,25 @@ Java_java_io_WinNTFileSystem_canonicalizeWithPrefix0(JNIEnv *env, jobject this,
return rv;
}
JNIEXPORT jstring JNICALL
Java_java_io_WinNTFileSystem_getFinalPath0(JNIEnv* env, jobject this, jstring pathname) {
jstring rv = NULL;
WITH_UNICODE_STRING(env, pathname, path) {
WCHAR* finalPath = getFinalPath(env, path);
if (finalPath != NULL) {
rv = (*env)->NewString(env, finalPath, (jsize)wcslen(finalPath));
free(finalPath);
}
} END_UNICODE_STRING(env, path);
if (rv == NULL && !(*env)->ExceptionCheck(env)) {
JNU_ThrowIOExceptionWithLastError(env, "Bad pathname");
}
return rv;
}
/* -- Attribute accessors -- */
/* Check whether or not the file name in "path" is a Windows reserved