[platform] getting rid of [somewhat speedier but nevertheless problematic] Windows FS helper

GitOrigin-RevId: 41b738ffb7c1fd3f4daf224782a9f2008a9d6b10
This commit is contained in:
Roman Shevchenko
2022-10-17 18:02:08 +02:00
committed by intellij-monorepo-bot
parent ef12c7f4bb
commit 4f73c9a0c3
15 changed files with 2 additions and 688 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -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

View File

@@ -1,3 +0,0 @@
/.idea/
/cmake-build-*/
/build-*/

View File

@@ -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})

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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

View File

@@ -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()
}
}
}

View File

@@ -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"})

View File

@@ -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;
}
}

View File

@@ -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);
}

View File

@@ -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());
}
}

View File

@@ -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());
}
}