mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-03-22 15:10:43 +07:00
[platform] getting rid of [somewhat speedier but nevertheless problematic] Windows FS helper
GitOrigin-RevId: 41b738ffb7c1fd3f4daf224782a9f2008a9d6b10
This commit is contained in:
committed by
intellij-monorepo-bot
parent
ef12c7f4bb
commit
4f73c9a0c3
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -675,7 +675,6 @@ com/intellij/ide/plugins/ModuleDependenciesDescriptor$ModuleReference.class:lib/
|
||||
com/intellij/ide/plugins/ModuleDependenciesDescriptor$PluginReference.class:lib/app.jar
|
||||
intellij.platform.feedback.xml:lib/app.jar
|
||||
intellij.notebooks.visualization.xml:lib/app.jar
|
||||
com/intellij/openapi/util/io/win32/IdeaWin32.class:lib/util.jar
|
||||
com/intellij/ui/RasterizedImageDataLoader.class:lib/app.jar
|
||||
intellij.platform.images.copyright.xml:lib/app.jar
|
||||
com/intellij/ui/icons/IconLoadMeasurer.class:lib/app.jar
|
||||
@@ -4061,7 +4060,6 @@ com/intellij/database/vfs/DbStorageFileType$Detector.class:plugins/DatabaseTools
|
||||
net/jpountz/xxhash/StreamingXXHash32JNI$Factory.class:lib/3rd-party-rt.jar
|
||||
com/intellij/ide/HelpTooltip$Header.class:lib/app.jar
|
||||
net/jpountz/xxhash/StreamingXXHash32.class:lib/3rd-party-rt.jar
|
||||
com/intellij/openapi/util/io/FileSystemUtil$IdeaWin32MediatorImpl.class:lib/util.jar
|
||||
net/jpountz/xxhash/StreamingXXHash32JNI.class:lib/3rd-party-rt.jar
|
||||
com/intellij/util/ui/JBUI$CurrentTheme$ContextHelp.class:lib/app.jar
|
||||
net/jpountz/xxhash/XXHash64.class:lib/3rd-party-rt.jar
|
||||
|
||||
3
native/IdeaWin32/.gitignore
vendored
3
native/IdeaWin32/.gitignore
vendored
@@ -1,3 +0,0 @@
|
||||
/.idea/
|
||||
/cmake-build-*/
|
||||
/build-*/
|
||||
@@ -1,40 +0,0 @@
|
||||
cmake_minimum_required(VERSION 3.1)
|
||||
project(IdeaWin32)
|
||||
include(CheckSymbolExists)
|
||||
|
||||
if(NOT WIN32)
|
||||
message(FATAL_ERROR "Windows only.")
|
||||
endif()
|
||||
|
||||
if (DEFINED ENV{BUILD_NUMBER})
|
||||
set(BUILD_NUMBER $ENV{BUILD_NUMBER})
|
||||
else()
|
||||
set(BUILD_NUMBER 9999)
|
||||
endif()
|
||||
|
||||
string(TIMESTAMP YEAR "%Y")
|
||||
|
||||
check_symbol_exists("_M_ARM64" "" TARGET_ARM64)
|
||||
check_symbol_exists("_M_AMD64" "" TARGET_X64)
|
||||
if(TARGET_ARM64)
|
||||
set(FILE_NAME "IdeaWin64a")
|
||||
set(JAVA_HOME $ENV{JDK_11_0_ARM64})
|
||||
elseif(TARGET_X64)
|
||||
set(FILE_NAME "IdeaWin64")
|
||||
set(JAVA_HOME $ENV{JDK_11_0_x64})
|
||||
else()
|
||||
set(FILE_NAME "IdeaWin32")
|
||||
set(JAVA_HOME $ENV{JDK_11_0})
|
||||
endif()
|
||||
if(NOT JAVA_HOME)
|
||||
message(FATAL_ERROR "JDK_11_0/JDK_11_0_x64/JDK_11_0_ARM64 variables not defined (x64=${TARGET_X64}, arm64=${TARGET_ARM64}).")
|
||||
endif()
|
||||
|
||||
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /MT")
|
||||
include_directories(${JAVA_HOME}/include ${JAVA_HOME}/include/win32)
|
||||
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/IdeaWin32.rc ${CMAKE_CURRENT_BINARY_DIR}/IdeaWin32.rc @ONLY)
|
||||
|
||||
add_library(IdeaWin32 SHARED IdeaWin32.c IdeaWin32.h ${CMAKE_CURRENT_BINARY_DIR}/IdeaWin32.rc)
|
||||
|
||||
set_target_properties(IdeaWin32 PROPERTIES OUTPUT_NAME ${FILE_NAME})
|
||||
@@ -1,313 +0,0 @@
|
||||
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
|
||||
#include "IdeaWin32.h"
|
||||
#include <stdbool.h>
|
||||
#include <windows.h>
|
||||
|
||||
typedef DWORD (WINAPI *GetFinalPathNameByHandlePtr)(HANDLE, LPCWSTR, DWORD, DWORD);
|
||||
static GetFinalPathNameByHandlePtr __GetFinalPathNameByHandle = NULL;
|
||||
|
||||
static jfieldID nameID = NULL;
|
||||
static jfieldID attributesID = NULL;
|
||||
static jfieldID timestampID = NULL;
|
||||
static jfieldID lengthID = NULL;
|
||||
|
||||
#define FILE_INFO_CLASS "com/intellij/openapi/util/io/win32/FileInfo"
|
||||
#define BROKEN_SYMLINK_ATTR ((DWORD)-1)
|
||||
#define IS_SET(flags, flag) (((flags) & (flag)) == (flag))
|
||||
#define FILE_SHARE_ALL (FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE)
|
||||
|
||||
static wchar_t *ToWinPath(JNIEnv *env, jstring path, boolean dirSuffix);
|
||||
static jobject CreateFileInfo(JNIEnv *env, wchar_t *path, boolean isDirectory, LPWIN32_FIND_DATAW lpData, jclass aClass);
|
||||
static jobjectArray CopyObjectArray(JNIEnv *env, jobjectArray src, jclass aClass, jsize count, jsize newSize);
|
||||
|
||||
|
||||
// interface methods
|
||||
|
||||
JNIEXPORT void JNICALL Java_com_intellij_openapi_util_io_win32_IdeaWin32_initIDs(JNIEnv *env, jclass cls) {
|
||||
__GetFinalPathNameByHandle = (GetFinalPathNameByHandlePtr)GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "GetFinalPathNameByHandleW");
|
||||
|
||||
jclass fileInfoClass = (*env)->FindClass(env, FILE_INFO_CLASS);
|
||||
if (fileInfoClass == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
nameID = (*env)->GetFieldID(env, fileInfoClass, "name", "Ljava/lang/String;");
|
||||
attributesID = (*env)->GetFieldID(env, fileInfoClass, "attributes", "I");
|
||||
timestampID = (*env)->GetFieldID(env, fileInfoClass, "timestamp", "J");
|
||||
lengthID = (*env)->GetFieldID(env, fileInfoClass, "length", "J");
|
||||
}
|
||||
|
||||
JNIEXPORT jobject JNICALL Java_com_intellij_openapi_util_io_win32_IdeaWin32_getInfo0(JNIEnv *env, jobject method, jstring path) {
|
||||
wchar_t *winPath = ToWinPath(env, path, false);
|
||||
if (winPath == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
WIN32_FILE_ATTRIBUTE_DATA attrData;
|
||||
BOOL res = GetFileAttributesExW(winPath, GetFileExInfoStandard, &attrData);
|
||||
if (!res) {
|
||||
free(winPath);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
jclass fileInfoClass = (*env)->FindClass(env, FILE_INFO_CLASS);
|
||||
if (fileInfoClass == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
jobject result = NULL;
|
||||
if (IS_SET(attrData.dwFileAttributes, FILE_ATTRIBUTE_REPARSE_POINT)) {
|
||||
// may be symlink
|
||||
WIN32_FIND_DATAW data;
|
||||
HANDLE h = FindFirstFileW(winPath, &data);
|
||||
if (h != INVALID_HANDLE_VALUE) {
|
||||
FindClose(h);
|
||||
result = CreateFileInfo(env, winPath, false, &data, fileInfoClass);
|
||||
}
|
||||
}
|
||||
if (result == NULL) {
|
||||
// either not a symlink or FindFirstFile() failed
|
||||
WIN32_FIND_DATAW data;
|
||||
data.dwFileAttributes = attrData.dwFileAttributes;
|
||||
data.dwReserved0 = 0;
|
||||
data.ftLastWriteTime = attrData.ftLastWriteTime;
|
||||
data.nFileSizeLow = attrData.nFileSizeLow;
|
||||
data.nFileSizeHigh = attrData.nFileSizeHigh;
|
||||
data.cFileName[0] = L'\0';
|
||||
result = CreateFileInfo(env, winPath, false, &data, fileInfoClass);
|
||||
}
|
||||
|
||||
free(winPath);
|
||||
return result;
|
||||
}
|
||||
|
||||
JNIEXPORT jstring JNICALL Java_com_intellij_openapi_util_io_win32_IdeaWin32_resolveSymLink0(JNIEnv *env, jobject method, jstring path) {
|
||||
if (__GetFinalPathNameByHandle == NULL) {
|
||||
return path; // links not supported
|
||||
}
|
||||
|
||||
wchar_t *winPath = ToWinPath(env, path, false);
|
||||
if (winPath == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (wcsncmp(winPath, L"\\\\?\\UNC\\", 8) == 0) {
|
||||
free(winPath);
|
||||
return path;
|
||||
}
|
||||
|
||||
jstring result = path;
|
||||
|
||||
HANDLE h = CreateFileW(winPath, 0, FILE_SHARE_ALL, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
|
||||
if (h != INVALID_HANDLE_VALUE) {
|
||||
wchar_t buff[MAX_PATH], *finalPath = buff;
|
||||
DWORD len = __GetFinalPathNameByHandle(h, buff, MAX_PATH, 0);
|
||||
if (len >= MAX_PATH) {
|
||||
finalPath = (wchar_t*)calloc(len + 1, sizeof(wchar_t));
|
||||
len = finalPath != NULL ? __GetFinalPathNameByHandle(h, finalPath, len, 0) : 0;
|
||||
}
|
||||
if (len > 0 && finalPath != NULL) {
|
||||
int prefix = 0;
|
||||
if (len > 8 && wcsncmp(finalPath, L"\\\\?\\UNC\\", 8) == 0) {
|
||||
prefix = 6;
|
||||
finalPath[6] = L'\\';
|
||||
} else if (len > 4 && finalPath[0] == L'\\' && finalPath[1] == L'\\' && finalPath[2] == L'?' && finalPath[3] == L'\\') {
|
||||
prefix = 4;
|
||||
}
|
||||
result = (*env)->NewString(env, (jchar*)finalPath + prefix, len - prefix);
|
||||
if (finalPath != buff) {
|
||||
free(finalPath);
|
||||
}
|
||||
}
|
||||
CloseHandle(h);
|
||||
} else {
|
||||
result = NULL;
|
||||
}
|
||||
|
||||
free(winPath);
|
||||
return result;
|
||||
}
|
||||
|
||||
JNIEXPORT jobjectArray JNICALL Java_com_intellij_openapi_util_io_win32_IdeaWin32_listChildren0(JNIEnv *env, jobject method, jstring path) {
|
||||
jclass fileInfoClass = (*env)->FindClass(env, FILE_INFO_CLASS);
|
||||
if (fileInfoClass == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
wchar_t *winPath = ToWinPath(env, path, true);
|
||||
if (winPath == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
WIN32_FIND_DATAW data;
|
||||
HANDLE h = FindFirstFileW(winPath, &data);
|
||||
if (h == INVALID_HANDLE_VALUE) {
|
||||
free(winPath);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
jsize len = 0, maxLen = 16;
|
||||
jobjectArray result = (*env)->NewObjectArray(env, maxLen, fileInfoClass, NULL);
|
||||
if (result != NULL) {
|
||||
do {
|
||||
if (wcscmp(data.cFileName, L".") == 0 || wcscmp(data.cFileName, L"..") == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (len == maxLen) {
|
||||
result = CopyObjectArray(env, result, fileInfoClass, len, maxLen <<= 1);
|
||||
if (result == NULL) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
jobject o = CreateFileInfo(env, winPath, true, &data, fileInfoClass);
|
||||
(*env)->SetObjectArrayElement(env, result, len++, o);
|
||||
(*env)->DeleteLocalRef(env, o);
|
||||
}
|
||||
while (FindNextFileW(h, &data));
|
||||
|
||||
if (len != maxLen) {
|
||||
result = CopyObjectArray(env, result, fileInfoClass, len, len);
|
||||
}
|
||||
}
|
||||
|
||||
free(winPath);
|
||||
FindClose(h);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// utility methods
|
||||
|
||||
static LONGLONG pairToInt64(DWORD lowPart, DWORD highPart) {
|
||||
ULARGE_INTEGER large;
|
||||
large.LowPart = lowPart;
|
||||
large.HighPart = highPart;
|
||||
return large.QuadPart;
|
||||
}
|
||||
|
||||
static wchar_t *ToWinPath(JNIEnv *env, jstring path, boolean dirSuffix) {
|
||||
size_t len = (size_t)((*env)->GetStringLength(env, path));
|
||||
const jchar *jstr = (*env)->GetStringChars(env, path, NULL);
|
||||
while (len > 0 && jstr[len - 1] == L'\\') --len; // trim trailing separators
|
||||
|
||||
if (len == 0) {
|
||||
(*env)->ReleaseStringChars(env, path, jstr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const wchar_t *prefix = L"\\\\?\\";
|
||||
size_t prefixLen = 4, skip = 0, suffixLen = dirSuffix ? 2 : 0;
|
||||
if (len == 2 && jstr[1] == L':') {
|
||||
prefix = L"";
|
||||
prefixLen = skip = 0;
|
||||
} else if (len > 2 && jstr[0] == L'\\' && jstr[1] == L'\\') {
|
||||
prefix = L"\\\\?\\UNC\\";
|
||||
prefixLen = 8;
|
||||
skip = 2;
|
||||
}
|
||||
|
||||
wchar_t *pathBuf = (wchar_t*)calloc(prefixLen + len - skip + suffixLen + 1, sizeof(wchar_t));
|
||||
if (pathBuf != NULL) {
|
||||
if (prefixLen > 0) {
|
||||
wcsncpy_s(pathBuf, prefixLen + 1, prefix, prefixLen);
|
||||
}
|
||||
wcsncpy_s(pathBuf + prefixLen, len - skip + 1, (wchar_t*)jstr + skip, len - skip);
|
||||
if (suffixLen > 0) {
|
||||
wcsncpy_s(pathBuf + prefixLen + len - skip, suffixLen + 1, L"\\*", suffixLen);
|
||||
}
|
||||
pathBuf[prefixLen + len - skip + suffixLen] = L'\0';
|
||||
|
||||
if (prefixLen > 0) {
|
||||
DWORD normLen = GetFullPathNameW(pathBuf, 0, NULL, NULL);
|
||||
if (normLen > 0) {
|
||||
wchar_t *normPathBuf = (wchar_t*)calloc(normLen, sizeof(wchar_t));
|
||||
if (normPathBuf != NULL) {
|
||||
GetFullPathNameW(pathBuf, normLen, normPathBuf, NULL);
|
||||
free(pathBuf);
|
||||
pathBuf = normPathBuf;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(*env)->ReleaseStringChars(env, path, jstr);
|
||||
|
||||
return pathBuf;
|
||||
}
|
||||
|
||||
static jobject CreateFileInfo(JNIEnv *env, wchar_t *path, boolean isDirectory, LPWIN32_FIND_DATAW lpData, jclass aClass) {
|
||||
DWORD attributes = lpData->dwFileAttributes;
|
||||
LONGLONG timestamp = pairToInt64(lpData->ftLastWriteTime.dwLowDateTime, lpData->ftLastWriteTime.dwHighDateTime);
|
||||
LONGLONG length = pairToInt64(lpData->nFileSizeLow, lpData->nFileSizeHigh);
|
||||
|
||||
if (IS_SET(attributes, FILE_ATTRIBUTE_REPARSE_POINT)) {
|
||||
if (IS_SET(lpData->dwReserved0, IO_REPARSE_TAG_SYMLINK) || IS_SET(lpData->dwReserved0, IO_REPARSE_TAG_MOUNT_POINT)) {
|
||||
attributes = BROKEN_SYMLINK_ATTR;
|
||||
timestamp = 0;
|
||||
length = 0;
|
||||
|
||||
wchar_t *fullPath = path;
|
||||
if (isDirectory) {
|
||||
// trim '*' and append file name
|
||||
size_t dirLen = wcslen(path) - 1, nameLen = wcslen(lpData->cFileName), fullLen = dirLen + nameLen + 1;
|
||||
fullPath = (wchar_t*)calloc(fullLen, sizeof(wchar_t));
|
||||
if (fullPath == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
wcsncpy_s(fullPath, dirLen + 1, path, dirLen);
|
||||
wcsncpy_s(fullPath + dirLen, nameLen + 1, lpData->cFileName, nameLen);
|
||||
}
|
||||
|
||||
// read reparse point target attributes
|
||||
HANDLE h = CreateFileW(fullPath, 0, FILE_SHARE_ALL, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
|
||||
if (h != INVALID_HANDLE_VALUE) {
|
||||
BY_HANDLE_FILE_INFORMATION targetData;
|
||||
if (GetFileInformationByHandle(h, &targetData)) {
|
||||
attributes = targetData.dwFileAttributes | FILE_ATTRIBUTE_REPARSE_POINT;
|
||||
timestamp = pairToInt64(targetData.ftLastWriteTime.dwLowDateTime, targetData.ftLastWriteTime.dwHighDateTime);
|
||||
length = pairToInt64(targetData.nFileSizeLow, targetData.nFileSizeHigh);
|
||||
}
|
||||
CloseHandle(h);
|
||||
}
|
||||
|
||||
if (fullPath != path) {
|
||||
free(fullPath);
|
||||
}
|
||||
} else {
|
||||
attributes &= (~ FILE_ATTRIBUTE_REPARSE_POINT); // keep the flag only for known reparse points
|
||||
}
|
||||
}
|
||||
|
||||
jobject o = (*env)->AllocObject(env, aClass);
|
||||
if (o == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
jstring fileName = (*env)->NewString(env, (jchar*)lpData->cFileName, (jsize)wcslen(lpData->cFileName));
|
||||
if (fileName == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
(*env)->SetObjectField(env, o, nameID, fileName);
|
||||
(*env)->SetIntField(env, o, attributesID, attributes);
|
||||
(*env)->SetLongField(env, o, timestampID, timestamp);
|
||||
(*env)->SetLongField(env, o, lengthID, length);
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
static jobjectArray CopyObjectArray(JNIEnv *env, jobjectArray src, jclass aClass, jsize count, jsize newSize) {
|
||||
jobjectArray dst = (*env)->NewObjectArray(env, newSize, aClass, NULL);
|
||||
if (dst != NULL) {
|
||||
for (jsize i = 0; i < count; i++) {
|
||||
jobject o = (*env)->GetObjectArrayElement(env, src, i);
|
||||
(*env)->SetObjectArrayElement(env, dst, i, o);
|
||||
(*env)->DeleteLocalRef(env, o);
|
||||
}
|
||||
}
|
||||
(*env)->DeleteLocalRef(env, src);
|
||||
return dst;
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
#ifndef _Included_com_intellij_openapi_util_io_win32_IdeaWin32
|
||||
#define _Included_com_intellij_openapi_util_io_win32_IdeaWin32
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
JNIEXPORT void JNICALL Java_com_intellij_openapi_util_io_win32_IdeaWin32_initIDs(JNIEnv *, jclass);
|
||||
|
||||
JNIEXPORT jobject JNICALL Java_com_intellij_openapi_util_io_win32_IdeaWin32_getInfo0(JNIEnv *, jobject, jstring);
|
||||
|
||||
JNIEXPORT jstring JNICALL Java_com_intellij_openapi_util_io_win32_IdeaWin32_resolveSymLink0(JNIEnv *, jobject, jstring);
|
||||
|
||||
JNIEXPORT jobjectArray JNICALL Java_com_intellij_openapi_util_io_win32_IdeaWin32_listChildren0(JNIEnv *, jobject, jstring);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@@ -1,35 +0,0 @@
|
||||
#define VERSION 1,2,0,@BUILD_NUMBER@
|
||||
#define VERSION_STR "1.2.0.@BUILD_NUMBER@\0"
|
||||
#define FILE_NAME "@FILE_NAME@.dll"
|
||||
#define COPYRIGHT "Copyright 2000-@YEAR@ JetBrains s.r.o."
|
||||
|
||||
#pragma code_page(65001)
|
||||
|
||||
1 VERSIONINFO
|
||||
FILEVERSION VERSION
|
||||
PRODUCTVERSION VERSION
|
||||
FILEFLAGSMASK 0x0L
|
||||
FILEFLAGS 0x0L
|
||||
FILEOS 0x4L
|
||||
FILETYPE 0x2L
|
||||
FILESUBTYPE 0x0L
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "0000fde9"
|
||||
BEGIN
|
||||
VALUE "CompanyName", "JetBrains s.r.o."
|
||||
VALUE "FileDescription", "Filesystem access helper library"
|
||||
VALUE "FileVersion", VERSION_STR
|
||||
VALUE "InternalName", FILE_NAME
|
||||
VALUE "LegalCopyright", COPYRIGHT
|
||||
VALUE "OriginalFilename", FILE_NAME
|
||||
VALUE "ProductName", "IntelliJ Platform"
|
||||
VALUE "ProductVersion", VERSION_STR
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0, 0xfde9
|
||||
END
|
||||
END
|
||||
@@ -34,7 +34,6 @@ import com.intellij.openapi.diagnostic.logger
|
||||
import com.intellij.openapi.util.Disposer
|
||||
import com.intellij.openapi.util.ShutDownTracker
|
||||
import com.intellij.openapi.util.SystemInfoRt
|
||||
import com.intellij.openapi.util.io.win32.IdeaWin32
|
||||
import com.intellij.openapi.wm.WeakFocusStackManager
|
||||
import com.intellij.serviceContainer.ComponentManagerImpl
|
||||
import com.intellij.ui.AppUIUtil
|
||||
@@ -314,9 +313,6 @@ private fun CoroutineScope.loadSystemLibsAndLogInfoAndInitMacApp(logDeferred: De
|
||||
withContext(Dispatchers.IO) {
|
||||
runActivity("system libs loading") {
|
||||
JnaLoader.load(log)
|
||||
if (SystemInfoRt.isWindows) {
|
||||
IdeaWin32.isAvailable()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,8 +4,6 @@ package com.intellij.openapi.util.io;
|
||||
import com.intellij.jna.JnaLoader;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.util.io.win32.FileInfo;
|
||||
import com.intellij.openapi.util.io.win32.IdeaWin32;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.CharsetToolkit;
|
||||
import com.intellij.util.SystemProperties;
|
||||
@@ -57,9 +55,6 @@ public final class FileSystemUtil {
|
||||
static @NotNull Mediator computeMediator() {
|
||||
if (!Boolean.getBoolean(FORCE_USE_NIO2_KEY)) {
|
||||
try {
|
||||
if (SystemInfo.isWindows && IdeaWin32.isAvailable()) {
|
||||
return ensureSane(new IdeaWin32MediatorImpl());
|
||||
}
|
||||
if ((SystemInfo.isLinux || SystemInfo.isMac) && CpuArch.isIntel64() && JnaLoader.isLoaded()) {
|
||||
return ensureSane(new JnaUnixMediatorImpl());
|
||||
}
|
||||
@@ -149,42 +144,6 @@ public final class FileSystemUtil {
|
||||
return resolveSymLink(file.getAbsolutePath());
|
||||
}
|
||||
|
||||
private static class IdeaWin32MediatorImpl implements Mediator {
|
||||
private final IdeaWin32 myInstance = IdeaWin32.getInstance();
|
||||
|
||||
@Override
|
||||
public FileAttributes getAttributes(@NotNull String path) {
|
||||
FileInfo fileInfo = myInstance.getInfo(path);
|
||||
return fileInfo != null ? fileInfo.toFileAttributes() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String resolveSymLink(@NotNull String path) {
|
||||
path = new File(path).getAbsolutePath();
|
||||
|
||||
if (!(path.length() > 3 && OSAgnosticPathUtil.isAbsoluteDosPath(path))) {
|
||||
return path; // unknown format
|
||||
}
|
||||
|
||||
int remainder = 4;
|
||||
while (remainder < path.length()) {
|
||||
int next = path.indexOf('\\', remainder);
|
||||
String subPath = next > 0 ? path.substring(0, next) : path;
|
||||
FileAttributes attributes = getAttributes(subPath);
|
||||
if (attributes == null) {
|
||||
return null;
|
||||
}
|
||||
if (attributes.isSymLink()) {
|
||||
return myInstance.resolveSymLink(path);
|
||||
}
|
||||
|
||||
remainder = next > 0 ? next + 1 : path.length();
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
}
|
||||
|
||||
// thanks to SVNKit for the idea of platform-specific offsets
|
||||
private static class JnaUnixMediatorImpl implements Mediator {
|
||||
@SuppressWarnings({"OctalInteger", "SpellCheckingInspection"})
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.openapi.util.io.win32;
|
||||
|
||||
import com.intellij.openapi.util.io.FileAttributes;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import static com.intellij.util.BitUtil.isSet;
|
||||
|
||||
/**
|
||||
* Do not use this class directly.
|
||||
*
|
||||
* @author Dmitry Avdeev
|
||||
*/
|
||||
public class FileInfo {
|
||||
private static final int BROKEN_SYMLINK = -1;
|
||||
private static final int FILE_ATTRIBUTE_READONLY = 0x0001;
|
||||
private static final int FILE_ATTRIBUTE_HIDDEN = 0x0002;
|
||||
private static final int FILE_ATTRIBUTE_DIRECTORY = 0x0010;
|
||||
private static final int FILE_ATTRIBUTE_DEVICE = 0x0040;
|
||||
private static final int FILE_ATTRIBUTE_REPARSE_POINT = 0x0400; // is set only for symlinks
|
||||
|
||||
@SuppressWarnings("UnusedDeclaration") private String name;
|
||||
@SuppressWarnings("UnusedDeclaration") private int attributes;
|
||||
@SuppressWarnings("UnusedDeclaration") private long timestamp;
|
||||
@SuppressWarnings("UnusedDeclaration") private long length;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public FileAttributes toFileAttributes() {
|
||||
if (attributes == BROKEN_SYMLINK) return FileAttributes.BROKEN_SYMLINK;
|
||||
|
||||
final boolean isDirectory = isSet(attributes, FILE_ATTRIBUTE_DIRECTORY);
|
||||
final boolean isSpecial = isSet(attributes, FILE_ATTRIBUTE_DEVICE);
|
||||
final boolean isSymlink = isSet(attributes, FILE_ATTRIBUTE_REPARSE_POINT);
|
||||
final boolean isHidden = isSet(attributes, FILE_ATTRIBUTE_HIDDEN);
|
||||
final boolean isWritable = !isSet(attributes, FILE_ATTRIBUTE_READONLY);
|
||||
final long javaTimestamp = timestamp / 10000 - 11644473600000L;
|
||||
return new FileAttributes(isDirectory, isSpecial, isSymlink, isHidden, length, javaTimestamp, isDirectory || isWritable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
@@ -1,134 +0,0 @@
|
||||
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.openapi.util.io.win32;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.SystemInfoRt;
|
||||
import com.intellij.openapi.util.io.FileUtilRt;
|
||||
import com.intellij.util.loader.NativeLibraryLoader;
|
||||
import com.intellij.util.system.CpuArch;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.zip.CRC32;
|
||||
|
||||
/**
|
||||
* Do not use this class directly.
|
||||
*
|
||||
* @author Dmitry Avdeev
|
||||
*/
|
||||
public final class IdeaWin32 {
|
||||
private static final Logger LOG = Logger.getInstance(IdeaWin32.class);
|
||||
private static final boolean TRACE_ENABLED = LOG.isTraceEnabled();
|
||||
|
||||
private static final IdeaWin32 ourInstance;
|
||||
|
||||
static {
|
||||
IdeaWin32 instance = null;
|
||||
if (SystemInfoRt.isWindows && Boolean.parseBoolean(System.getProperty("idea.use.native.fs.for.win", "true"))) {
|
||||
try {
|
||||
if (!loadBundledLibrary()) {
|
||||
NativeLibraryLoader.loadPlatformLibrary("IdeaWin32");
|
||||
}
|
||||
instance = new IdeaWin32();
|
||||
LOG.info("Native filesystem for Windows is operational");
|
||||
}
|
||||
catch (Throwable t) {
|
||||
LOG.warn("Failed to initialize native filesystem for Windows", t);
|
||||
}
|
||||
}
|
||||
ourInstance = instance;
|
||||
}
|
||||
|
||||
private static boolean loadBundledLibrary() throws IOException {
|
||||
String name = CpuArch.isArm64() ? "IdeaWin64a" : CpuArch.isIntel64() ? "IdeaWin64" : "IdeaWin32";
|
||||
URL bundled = IdeaWin32.class.getResource(name + ".dll");
|
||||
if (bundled == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
byte[] content = FileUtilRt.loadBytes(bundled.openStream());
|
||||
CRC32 crc32 = new CRC32();
|
||||
crc32.update(content, 0, content.length);
|
||||
long hash = Math.abs(crc32.getValue());
|
||||
Path file = Paths.get(FileUtilRt.getTempDirectory(), name + '.' + hash + ".dll");
|
||||
if (!Files.exists(file)) {
|
||||
Files.createDirectories(file.getParent());
|
||||
Files.write(file, content);
|
||||
}
|
||||
System.load(file.toString());
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean isAvailable() {
|
||||
return ourInstance != null;
|
||||
}
|
||||
|
||||
public static @NotNull IdeaWin32 getInstance() {
|
||||
if (!isAvailable()) {
|
||||
throw new IllegalStateException("Native filesystem for Windows is not loaded");
|
||||
}
|
||||
return ourInstance;
|
||||
}
|
||||
|
||||
private IdeaWin32() {
|
||||
initIDs();
|
||||
}
|
||||
|
||||
private static native void initIDs();
|
||||
|
||||
public @Nullable FileInfo getInfo(@NotNull String path) {
|
||||
path = path.replace('/', '\\');
|
||||
if (TRACE_ENABLED) {
|
||||
LOG.trace("getInfo(" + path + ")");
|
||||
long t = System.nanoTime();
|
||||
FileInfo result = getInfo0(path);
|
||||
t = (System.nanoTime() - t) / 1000;
|
||||
LOG.trace(" " + t + " mks");
|
||||
return result;
|
||||
}
|
||||
else {
|
||||
return getInfo0(path);
|
||||
}
|
||||
}
|
||||
|
||||
public @Nullable String resolveSymLink(@NotNull String path) {
|
||||
path = path.replace('/', '\\');
|
||||
if (TRACE_ENABLED) {
|
||||
LOG.trace("resolveSymLink(" + path + ")");
|
||||
long t = System.nanoTime();
|
||||
String result = resolveSymLink0(path);
|
||||
t = (System.nanoTime() - t) / 1000;
|
||||
LOG.trace(" " + t + " mks");
|
||||
return result;
|
||||
}
|
||||
else {
|
||||
return resolveSymLink0(path);
|
||||
}
|
||||
}
|
||||
|
||||
public FileInfo @Nullable [] listChildren(@NotNull String path) {
|
||||
path = path.replace('/', '\\');
|
||||
if (TRACE_ENABLED) {
|
||||
LOG.trace("list(" + path + ")");
|
||||
long t = System.nanoTime();
|
||||
FileInfo[] children = listChildren0(path);
|
||||
t = (System.nanoTime() - t) / 1000;
|
||||
LOG.trace(" " + (children == null ? -1 : children.length) + " children, " + t + " mks");
|
||||
return children;
|
||||
}
|
||||
else {
|
||||
return listChildren0(path);
|
||||
}
|
||||
}
|
||||
|
||||
private native FileInfo getInfo0(String path);
|
||||
|
||||
private native String resolveSymLink0(String path);
|
||||
|
||||
private native FileInfo[] listChildren0(String path);
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.util.loader;
|
||||
|
||||
import com.intellij.openapi.application.PathManager;
|
||||
import com.intellij.util.system.CpuArch;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Arrays;
|
||||
|
||||
public final class NativeLibraryLoader {
|
||||
public static void loadPlatformLibrary(@NotNull String libName) {
|
||||
String baseName = libName;
|
||||
if (CpuArch.isIntel64()) {
|
||||
baseName = baseName.replace("32", "") + "64";
|
||||
} else if (CpuArch.isArm64()) {
|
||||
baseName = baseName.replace("32", "") + "64a";
|
||||
}
|
||||
|
||||
String libFileName = System.mapLibraryName(baseName).replace(".jnilib", ".dylib");
|
||||
Path libFile = PathManager.findBinFile(libFileName);
|
||||
if (libFile == null) {
|
||||
File libDir = new File(PathManager.getBinPath());
|
||||
throw new UnsatisfiedLinkError("'" + libFileName + "' not found in '" + libDir + "' among " + Arrays.toString(libDir.list()));
|
||||
}
|
||||
|
||||
System.load(libFile.toString());
|
||||
}
|
||||
}
|
||||
@@ -29,8 +29,8 @@ public abstract class FileAttributesReadingTest {
|
||||
public static class MainTest extends FileAttributesReadingTest {
|
||||
@BeforeClass
|
||||
public static void setUpClass() {
|
||||
assumeTrue(SystemInfo.OS_NAME + '/' + CpuArch.CURRENT + " is not supported", CpuArch.isIntel64());
|
||||
assertEquals(SystemInfo.isWindows ? "IdeaWin32" : "JnaUnix", getMediatorName());
|
||||
assumeTrue(SystemInfo.OS_NAME + '/' + CpuArch.CURRENT + " is not supported", CpuArch.isIntel64() && !SystemInfo.isWindows);
|
||||
assertEquals("JnaUnix", getMediatorName());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user