From d2cba8e460c0003a20264571f2eb513f6a132217 Mon Sep 17 00:00:00 2001 From: Andrey Loskutov Date: Thu, 2 Jul 2026 17:32:57 +0200 Subject: [PATCH 1/2] Bump org.eclipse.core.filesystem.linux.x86_64 and tests version for 4.41 --- .../META-INF/MANIFEST.MF | 4 ++-- .../bundles/org.eclipse.core.filesystem.linux.x86_64/pom.xml | 2 +- .../org.eclipse.core.tests.resources/META-INF/MANIFEST.MF | 2 +- resources/tests/org.eclipse.core.tests.resources/pom.xml | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/resources/bundles/org.eclipse.core.filesystem.linux.x86_64/META-INF/MANIFEST.MF b/resources/bundles/org.eclipse.core.filesystem.linux.x86_64/META-INF/MANIFEST.MF index ada3f4f2eeb..c87b4505a56 100644 --- a/resources/bundles/org.eclipse.core.filesystem.linux.x86_64/META-INF/MANIFEST.MF +++ b/resources/bundles/org.eclipse.core.filesystem.linux.x86_64/META-INF/MANIFEST.MF @@ -2,8 +2,8 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %fragmentName Bundle-SymbolicName: org.eclipse.core.filesystem.linux.x86_64; singleton:=true -Bundle-Version: 1.2.400.qualifier +Bundle-Version: 1.2.500.qualifier Bundle-Vendor: %providerName -Fragment-Host: org.eclipse.core.filesystem;bundle-version="[1.7.200,2.0.0)" +Fragment-Host: org.eclipse.core.filesystem;bundle-version="[1.11.500,2.0.0)" Bundle-Localization: fragment Eclipse-PlatformFilter: (& (osgi.os=linux) (osgi.arch=x86_64)) diff --git a/resources/bundles/org.eclipse.core.filesystem.linux.x86_64/pom.xml b/resources/bundles/org.eclipse.core.filesystem.linux.x86_64/pom.xml index 1d83bb509fd..3141d7d51dd 100644 --- a/resources/bundles/org.eclipse.core.filesystem.linux.x86_64/pom.xml +++ b/resources/bundles/org.eclipse.core.filesystem.linux.x86_64/pom.xml @@ -18,7 +18,7 @@ ../../ org.eclipse.core.filesystem.linux.x86_64 - 1.2.400-SNAPSHOT + 1.2.500-SNAPSHOT eclipse-plugin diff --git a/resources/tests/org.eclipse.core.tests.resources/META-INF/MANIFEST.MF b/resources/tests/org.eclipse.core.tests.resources/META-INF/MANIFEST.MF index 4c0d18e2363..e7c73a23e09 100644 --- a/resources/tests/org.eclipse.core.tests.resources/META-INF/MANIFEST.MF +++ b/resources/tests/org.eclipse.core.tests.resources/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Eclipse Core Tests Resources Bundle-SymbolicName: org.eclipse.core.tests.resources; singleton:=true -Bundle-Version: 3.11.1300.qualifier +Bundle-Version: 3.11.1400.qualifier Bundle-Vendor: Eclipse.org Export-Package: org.eclipse.core.tests.filesystem, org.eclipse.core.tests.internal.alias, diff --git a/resources/tests/org.eclipse.core.tests.resources/pom.xml b/resources/tests/org.eclipse.core.tests.resources/pom.xml index 22616439ded..1b96a3106a3 100644 --- a/resources/tests/org.eclipse.core.tests.resources/pom.xml +++ b/resources/tests/org.eclipse.core.tests.resources/pom.xml @@ -18,7 +18,7 @@ 4.41.0-SNAPSHOT org.eclipse.core.tests.resources - 3.11.1300-SNAPSHOT + 3.11.1400-SNAPSHOT eclipse-test-plugin From 8f4ede3898b8a5fe2e31884a11a93f54dba836b7 Mon Sep 17 00:00:00 2001 From: Andrey Loskutov Date: Tue, 30 Jun 2026 17:55:13 +0200 Subject: [PATCH 2/2] Introduce faster file refresh on Linux (x86_64 only for now) The code is supposed to speed up NFS file access on Linux by an order of magnitude by fetching directory children data (IFileInfo) in one shot from JNI (via array of StructStat). LocalFile.childInfos(int, IProgressMonitor) overrides now the FileStore.childInfos(int, IProgressMonitor) and calls (on Linux) LinuxFileHandler.listDirectoryAndGetFileInfos() which forwards to faster native implementation in LinuxFileNatives.listDirectoryAndGetFileInfos(). - Introduced new libfastlinuxfile_1_0_0 library for x86_64 Linux architecture (which can be also built on other Linux architectures). - Created dedicated Linux specific package org.eclipse.core.internal.filesystem.local.linux - removed Mac code paths from new code to simplify Linux port - Added system property to disable new binary if needed via "-Declipse.filesystem.useFastLinuxNatives=false" --- .../os/linux/x86_64/libfastlinuxfile_1_0_0.so | Bin 0 -> 18808 bytes .../pom.xml | 18 +- .../natives/unix/fastlinux/Makefile | 42 ++ .../natives/unix/fastlinux/fastlinuxfile.c | 578 ++++++++++++++++++ .../natives/unix/fastlinux/fastlinuxfile.h | 105 ++++ .../local/LocalFileNativesManager.java | 15 +- .../local/linux/LinuxFileFlags.java | 88 +++ .../local/linux/LinuxFileHandler.java | 48 ++ .../local/linux/LinuxFileNatives.java | 234 +++++++ .../local/linux/LinuxStructStat.java | 94 +++ .../filesystem/local/unix/StructStat.java | 19 +- .../local/unix/UnixFileNatives.java | 43 +- .../tests/resources/perf/BenchFileStore.java | 32 +- 13 files changed, 1268 insertions(+), 48 deletions(-) create mode 100644 resources/bundles/org.eclipse.core.filesystem.linux.x86_64/os/linux/x86_64/libfastlinuxfile_1_0_0.so create mode 100644 resources/bundles/org.eclipse.core.filesystem/natives/unix/fastlinux/Makefile create mode 100644 resources/bundles/org.eclipse.core.filesystem/natives/unix/fastlinux/fastlinuxfile.c create mode 100644 resources/bundles/org.eclipse.core.filesystem/natives/unix/fastlinux/fastlinuxfile.h create mode 100644 resources/bundles/org.eclipse.core.filesystem/src/org/eclipse/core/internal/filesystem/local/linux/LinuxFileFlags.java create mode 100644 resources/bundles/org.eclipse.core.filesystem/src/org/eclipse/core/internal/filesystem/local/linux/LinuxFileHandler.java create mode 100644 resources/bundles/org.eclipse.core.filesystem/src/org/eclipse/core/internal/filesystem/local/linux/LinuxFileNatives.java create mode 100644 resources/bundles/org.eclipse.core.filesystem/src/org/eclipse/core/internal/filesystem/local/linux/LinuxStructStat.java diff --git a/resources/bundles/org.eclipse.core.filesystem.linux.x86_64/os/linux/x86_64/libfastlinuxfile_1_0_0.so b/resources/bundles/org.eclipse.core.filesystem.linux.x86_64/os/linux/x86_64/libfastlinuxfile_1_0_0.so new file mode 100644 index 0000000000000000000000000000000000000000..dcb1925e3a63d19c42d0bfc100ad4fabc35efd77 GIT binary patch literal 18808 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 K#C=wE>|X)T;*5*{ literal 0 HcmV?d00001 diff --git a/resources/bundles/org.eclipse.core.filesystem.linux.x86_64/pom.xml b/resources/bundles/org.eclipse.core.filesystem.linux.x86_64/pom.xml index 3141d7d51dd..f54da5cba35 100644 --- a/resources/bundles/org.eclipse.core.filesystem.linux.x86_64/pom.xml +++ b/resources/bundles/org.eclipse.core.filesystem.linux.x86_64/pom.xml @@ -5,7 +5,7 @@ are made available under the terms of the Eclipse Distribution License v1.0 which accompanies this distribution, and is available at http://www.eclipse.org/org/documents/edl-v10.php - + Contributors: Igor Fedorenko - initial implementation --> @@ -42,12 +42,16 @@ - - - - - - + + + + + + + + + + diff --git a/resources/bundles/org.eclipse.core.filesystem/natives/unix/fastlinux/Makefile b/resources/bundles/org.eclipse.core.filesystem/natives/unix/fastlinux/Makefile new file mode 100644 index 00000000000..13c720d773f --- /dev/null +++ b/resources/bundles/org.eclipse.core.filesystem/natives/unix/fastlinux/Makefile @@ -0,0 +1,42 @@ +#****************************************************************************** +# Copyright (c) 2010 IBM Corporation and others. +# +# This program and the accompanying materials +# are made available under the terms of the Eclipse Public License 2.0 +# which accompanies this distribution, and is available at +# https://www.eclipse.org/legal/epl-2.0/ +# +# SPDX-License-Identifier: EPL-2.0 +# +# Contributors: +# IBM Corporation - initial API and implementation +#******************************************************************************/ +# +# makefile for libfastlinuxfile_1_0_0.so + +CORE.C = fastlinuxfile.c +CORE.O = fastlinuxfile.o +LIB_NAME = libfastlinuxfile.so +LIB_NAME_FULL = libfastlinuxfile_1_0_0.so + +#Set this to be your OS type +OS_TYPE = linux + +#Set this to be the location of your JRE +ifeq (${JAVA_HOME},) + JAVA_HOME = /usr/lib/jvm/java-17/ +endif + +JDK_INCLUDE = -I ${JAVA_HOME}/include -I ${JAVA_HOME}/include/${OS_TYPE} +OPT_FLAGS=-O2 -g -s -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 + +core: + gcc $(OPT_FLAGS) -fPIC -c $(JDK_INCLUDE) -o $(CORE.O) $(CORE.C) + gcc $(OPT_FLAGS) -shared -Wl,-soname,$(LIB_NAME) -o $(LIB_NAME_FULL) $(CORE.O) -lc + +clean: + rm -f $(CORE.O) $(LIB_NAME_FULL) + +install: core + rm -f ../../../../org.eclipse.core.filesystem.linux.x86_64/os/linux/x86_64/libfastlinuxfile_1_0_0.so + mv libfastlinuxfile_1_0_0.so ../../../../org.eclipse.core.filesystem.linux.x86_64/os/linux/x86_64/ diff --git a/resources/bundles/org.eclipse.core.filesystem/natives/unix/fastlinux/fastlinuxfile.c b/resources/bundles/org.eclipse.core.filesystem/natives/unix/fastlinux/fastlinuxfile.c new file mode 100644 index 00000000000..7e10ff47ac0 --- /dev/null +++ b/resources/bundles/org.eclipse.core.filesystem/natives/unix/fastlinux/fastlinuxfile.c @@ -0,0 +1,578 @@ +/******************************************************************************* + * Copyright (c) 2010 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "fastlinuxfile.h" + +/* The lstat stat field st_mode. */ +static jfieldID attrs_st_mode; +/* The lstat stat field st_size. */ +static jfieldID attrs_st_size; +/* The lstat stat field st_mtime_sec. */ +static jfieldID attrs_st_mtime; +/* The lstat stat field st_mtime_nsec divided by 1 000 000. */ +static jfieldID attrs_st_mtime_msec; + +static jfieldID errno_fieldID; + +static jfieldID nameFieldId; + +static jfieldID linkFieldId; + +static const jsize INITIAL_LIST_ARRAY_SIZE = 100; + +/* + * Class: Java_org_eclipse_core_internal_filesystem_local_linux_LinuxFileNatives_initializeLinuxStructStatFieldIDs + * Method: initializeLinuxStructStatFieldIDs + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_org_eclipse_core_internal_filesystem_local_linux_LinuxFileNatives_initializeLinuxStructStatFieldIDs + (JNIEnv *env, jclass clazz) +{ + jclass LinuxStructStatClass = (*env)->FindClass(env, "org/eclipse/core/internal/filesystem/local/linux/LinuxStructStat"); + if (LinuxStructStatClass == NULL) { + return; /* exception already pending */ + } + attrs_st_mode = (*env)->GetFieldID(env, LinuxStructStatClass, "st_mode", "I"); + attrs_st_size = (*env)->GetFieldID(env, LinuxStructStatClass, "st_size", "J"); + attrs_st_mtime = (*env)->GetFieldID(env, LinuxStructStatClass, "st_mtime", "J"); + errno_fieldID = (*env)->GetFieldID(env, LinuxStructStatClass, "errno", "I"); + nameFieldId = (*env)->GetFieldID(env, LinuxStructStatClass, "name", "[B"); + linkFieldId = (*env)->GetFieldID(env, LinuxStructStatClass, "linkFile", "[B"); + attrs_st_mtime_msec = (*env)->GetFieldID(env, LinuxStructStatClass, "st_mtime_msec", "J"); +} + +/* + * Get a null-terminated byte array from a java byte array. The returned bytearray + * needs to be freed when not used anymore. Use free(result) to do that. + */ +jbyte* getByteArray(JNIEnv *env, jbyteArray target) +{ + unsigned int len; + jbyte *temp, *result; + + temp = (*env)->GetByteArrayElements(env, target, 0); + len = (*env)->GetArrayLength(env, target); + result = malloc((len + 1) * sizeof(jbyte)); + if (result != NULL) { + memcpy(result, temp, len * sizeof(jbyte)); + result[len] = '\0'; + } + (*env)->ReleaseByteArrayElements(env, target, temp, 0); + return result; +} + +/* + * Copy object array contents using java.lang.System.arraycopy. + */ +jint copyObjectArray(JNIEnv *env, jobject source, jobject target, jsize length) +{ + jclass systemClass; + jmethodID arraycopyMethod; + + systemClass = (*env)->FindClass(env, "java/lang/System"); + if (systemClass == NULL) { + return -1; + } + arraycopyMethod = (*env)->GetStaticMethodID(env, systemClass, "arraycopy", "(Ljava/lang/Object;ILjava/lang/Object;II)V"); + if (arraycopyMethod == NULL) { + (*env)->DeleteLocalRef(env, systemClass); + return -1; + } + + (*env)->CallStaticVoidMethod(env, systemClass, arraycopyMethod, source, 0, target, 0, length); + (*env)->DeleteLocalRef(env, systemClass); + if ((*env)->ExceptionCheck(env)){ + return -1; + } + + return 0; +} + +/* + * Fills LinuxStructStat object with data from struct stat. + */ +jint convertStatToObject(JNIEnv *env, struct stat info, int errnoValue, jobject stat_object) +{ + if (attrs_st_mode == 0) return -1; + (*env)->SetIntField(env, stat_object, attrs_st_mode, info.st_mode); + + if (attrs_st_size == 0) return -1; + (*env)->SetLongField(env, stat_object, attrs_st_size, info.st_size); + + if (attrs_st_mtime == 0) return -1; + (*env)->SetLongField(env, stat_object, attrs_st_mtime, info.st_mtime); + + if (errno_fieldID == 0) return -1; + (*env)->SetIntField(env, stat_object, errno_fieldID, errnoValue); + + if (attrs_st_mtime_msec == 0) return -1; + (*env)->SetLongField(env, stat_object, attrs_st_mtime_msec, (info.st_mtim.tv_nsec / (1000 * 1000))); + + return 0; +} + +/* + * Class: org_eclipse_core_internal_filesystem_local_linux_LinuxFileNatives + * Method: chmod + * Signature: ([BI)I + */ +JNIEXPORT jint JNICALL Java_org_eclipse_core_internal_filesystem_local_linux_LinuxFileNatives_chmod + (JNIEnv *env, jclass clazz, jbyteArray path, jint mode) +{ + int code; + char *name; + + name = (char*) getByteArray(env, path); + if (name == NULL) { + return -1; + } + code = chmod(name, mode); + free(name); + return code; +} + +/* + * Class: org_eclipse_core_internal_filesystem_local_linux_LinuxFileNatives + * Method: stat + * Signature: ([BLorg/eclipse/core/internal/filesystem/local/linux/LinuxStructStat;)I + */ +JNIEXPORT jint JNICALL Java_org_eclipse_core_internal_filesystem_local_linux_LinuxFileNatives_stat + (JNIEnv *env, jclass clazz, jbyteArray path, jobject buf) +{ + jint code; + char *name; + struct stat info = {0}; + + name = (char*) getByteArray(env, path); + if (name == NULL) { + return -1; + } + code = fstatat(AT_FDCWD, name, &info, 0); + free(name); + return convertStatToObject(env, info, code == 0 ? 0 : errno, buf); +} + +/* + * Class: org_eclipse_core_internal_filesystem_local_linux_LinuxFileNatives + * Method: lstat + * Signature: ([BLorg/eclipse/core/internal/filesystem/local/linux/LinuxStructStat;)I + */ +JNIEXPORT jint JNICALL Java_org_eclipse_core_internal_filesystem_local_linux_LinuxFileNatives_lstat + (JNIEnv *env, jclass clazz, jbyteArray path, jobject buf) +{ + jint code; + char *name; + struct stat info = {0}; + + name = (char*) getByteArray(env, path); + if (name == NULL) { + return -1; + } + code = fstatat(AT_FDCWD, name, &info, AT_SYMLINK_NOFOLLOW); + free(name); + return convertStatToObject(env, info, code == 0 ? 0 : errno, buf); +} + +/* + * Class: org_eclipse_core_internal_filesystem_local_linux_LinuxFileNatives + * Method: readlink + * Signature: ([B[BJ)I + */ +JNIEXPORT jint JNICALL Java_org_eclipse_core_internal_filesystem_local_linux_LinuxFileNatives_readlink + (JNIEnv *env, jclass clazz, jbyteArray path, jbyteArray buf, jlong bufsiz) { + jbyte *name; + int len; + char temp[PATH_MAX+1]; + + name = getByteArray(env, path); + if (name == NULL) { + return -1; + } + len = readlink((const char*)name, temp, PATH_MAX); + free(name); + if (len > 0) { + temp[len] = 0; + (*env)->SetByteArrayRegion(env, buf, 0, len, (jbyte*) temp); + } + else { + temp[0] = 0; + (*env)->SetByteArrayRegion(env, buf, 0, 0, (jbyte*) temp); + } + return len; +} + +/* + * Class: org_eclipse_core_internal_filesystem_local_linux_LinuxFileNatives + * Method: getflag + * Signature: ([B)I + */ +JNIEXPORT jint JNICALL Java_org_eclipse_core_internal_filesystem_local_linux_LinuxFileNatives_getflag + (JNIEnv *env, jclass clazz, jbyteArray buf) +{ + char *flag; + jint ret = -1; + + flag = (char*) getByteArray(env, buf); + if (flag == NULL) { + return -1; + } + if (strcmp(flag, "PATH_MAX") == 0) + ret = PATH_MAX; + else if (strcmp(flag, "S_IFMT") == 0) + ret = S_IFMT; + else if (strcmp(flag, "S_IFLNK") == 0) + ret = S_IFLNK; + else if (strcmp(flag, "S_IFDIR") == 0) + ret = S_IFDIR; + else if (strcmp(flag, "S_IRUSR") == 0) + ret = S_IRUSR; + else if (strcmp(flag, "S_IWUSR") == 0) + ret = S_IWUSR; + else if (strcmp(flag, "S_IXUSR") == 0) + ret = S_IXUSR; + else if (strcmp(flag, "S_IRGRP") == 0) + ret = S_IRGRP; + else if (strcmp(flag, "S_IWGRP") == 0) + ret = S_IWGRP; + else if (strcmp(flag, "S_IXGRP") == 0) + ret = S_IXGRP; + else if (strcmp(flag, "S_IROTH") == 0) + ret = S_IROTH; + else if (strcmp(flag, "S_IWOTH") == 0) + ret = S_IWOTH; + else if (strcmp(flag, "S_IXOTH") == 0) + ret = S_IXOTH; + free(flag); + return ret; +} + +JNIEXPORT jobjectArray JNICALL Java_org_eclipse_core_internal_filesystem_local_linux_LinuxFileNatives_listDir + (JNIEnv *env, jclass, jbyteArray path) +{ + char *name; + DIR *dir = NULL; + jsize arrayLength; + int count = 0; + int i; + struct dirent *entry; + jobjectArray namesArray; + jobjectArray resultStatsArray = NULL; + jobjectArray result = NULL; + jclass byteArrayClass; + + byteArrayClass = (*env)->FindClass(env, "[B"); + if (byteArrayClass == NULL) { + return NULL; + } + namesArray = (*env)->NewObjectArray(env, INITIAL_LIST_ARRAY_SIZE, byteArrayClass, NULL); + if (namesArray == NULL) { + return NULL; + } + arrayLength = INITIAL_LIST_ARRAY_SIZE; + + name = (char*) getByteArray(env, path); + if (name == NULL) { + goto cleanup; + } + dir = opendir(name); + free(name); + if (dir == NULL) { + goto cleanup; + } + while ((entry = readdir(dir)) != NULL) { + jbyteArray nameBytes; + jsize nameLen; + jobjectArray grownArray; + + /* Skip . and .. */ + if (entry->d_name[0] == '.' && + (entry->d_name[1] == '\0' || + (entry->d_name[1] == '.' && entry->d_name[2] == '\0'))) { + continue; + } + + if (count >= arrayLength) { + jsize newLength = arrayLength > 0 ? arrayLength * 2 : 1; + + if (newLength < arrayLength) { + goto cleanup; + } + + grownArray = (*env)->NewObjectArray(env, newLength, byteArrayClass, NULL); + if (grownArray == NULL) { + goto cleanup; + } + + if (copyObjectArray(env, namesArray, grownArray, arrayLength) != 0) { + (*env)->DeleteLocalRef(env, grownArray); + goto cleanup; + } + + (*env)->DeleteLocalRef(env, namesArray); + namesArray = grownArray; + arrayLength = newLength; + } + + /* Add the directory entry name as raw bytes to the names array */ + nameLen = (jsize)strlen(entry->d_name); + nameBytes = (*env)->NewByteArray(env, nameLen); + if (nameBytes == NULL) { + goto cleanup; + } + (*env)->SetByteArrayRegion(env, nameBytes, 0, nameLen, (const jbyte*)entry->d_name); + (*env)->SetObjectArrayElement(env, namesArray, count, nameBytes); + (*env)->DeleteLocalRef(env, nameBytes); + if ((*env)->ExceptionCheck(env)) { + goto cleanup; + } + + count++; + } + + resultStatsArray = (*env)->NewObjectArray(env, count, byteArrayClass, NULL); + if (resultStatsArray == NULL) { + goto cleanup; + } + + for (i = 0; i < count; i++) { + jobject existingName = (*env)->GetObjectArrayElement(env, namesArray, i); + if ((*env)->ExceptionCheck(env)) { + goto cleanup; + } + (*env)->SetObjectArrayElement(env, resultStatsArray, i, existingName); + (*env)->DeleteLocalRef(env, existingName); + if ((*env)->ExceptionCheck(env)) { + goto cleanup; + } + } + + result = resultStatsArray; + resultStatsArray = NULL; + +cleanup: + if (dir != NULL) { + closedir(dir); + } + if (namesArray != NULL) { + (*env)->DeleteLocalRef(env, namesArray); + } + if (resultStatsArray != NULL) { + (*env)->DeleteLocalRef(env, resultStatsArray); + } + return result; +} + +JNIEXPORT jobjectArray JNICALL Java_org_eclipse_core_internal_filesystem_local_linux_LinuxFileNatives_listDirAndGetFileInfos + (JNIEnv *env, jclass, jbyteArray path) +{ + char *name; + DIR *dir = NULL; + int directoryFd; + jsize arrayLength; + int count = 0; + int i; + struct dirent *entry; + jclass LinuxStructStatClass; + jmethodID LinuxStructStatCtor; + jobjectArray statArray = NULL; + jobjectArray resultStatsArray = NULL; + jobjectArray result = NULL; + + LinuxStructStatClass = (*env)->FindClass(env, "org/eclipse/core/internal/filesystem/local/linux/LinuxStructStat"); + if (LinuxStructStatClass == NULL) { + return NULL; + } + + statArray = (*env)->NewObjectArray(env, INITIAL_LIST_ARRAY_SIZE, LinuxStructStatClass, NULL); + if (statArray == NULL) { + return NULL; + } + arrayLength = INITIAL_LIST_ARRAY_SIZE; + + LinuxStructStatCtor = (*env)->GetMethodID(env, LinuxStructStatClass, "", "()V"); + if (LinuxStructStatCtor == NULL) { + goto cleanup; + } + name = (char*) getByteArray(env, path); + if (name == NULL) { + goto cleanup; + } + dir = opendir(name); + free(name); + if (dir == NULL) { + goto cleanup; + } + directoryFd = dirfd(dir); + if (directoryFd == -1) { + goto cleanup; + } + while ((entry = readdir(dir)) != NULL) { + struct stat st; + jobject statObject = NULL; + int statErrno = 0; + + /* Skip . and .. */ + if (entry->d_name[0] == '.' && + (entry->d_name[1] == '\0' || + (entry->d_name[1] == '.' && entry->d_name[2] == '\0'))) { + continue; + } + + if (count >= arrayLength) { + jsize newLength = arrayLength > 0 ? arrayLength * 2 : 1; + jobjectArray grownStatArray; + + if (newLength < arrayLength) { + goto cleanup; + } + + grownStatArray = (*env)->NewObjectArray(env, newLength, LinuxStructStatClass, NULL); + if (grownStatArray == NULL) { + goto cleanup; + } + + if (copyObjectArray(env, statArray, grownStatArray, arrayLength) != 0) { + (*env)->DeleteLocalRef(env, grownStatArray); + goto cleanup; + } + + (*env)->DeleteLocalRef(env, statArray); + + statArray = grownStatArray; + arrayLength = newLength; + } + + statObject = (*env)->NewObject(env, LinuxStructStatClass, LinuxStructStatCtor); + if (statObject == NULL) { + goto cleanup; + } + + /* Collect file stats. Keep processing even if stat/readlink fails. */ + if (fstatat(directoryFd, entry->d_name, &st, AT_SYMLINK_NOFOLLOW) != 0) { + memset(&st, 0, sizeof(st)); + statErrno = errno; + } else if (S_ISLNK(st.st_mode)) { + char linkPath[PATH_MAX + 1]; + jbyteArray linkBytes; + jsize linkLen; + ssize_t linkPathLen; + + /* Follow symlink and update stat for further processing. */ + if (fstatat(directoryFd, entry->d_name, &st, 0) != 0) { + memset(&st, 0, sizeof(st)); + statErrno = errno; + } + + /* Read link target if possible. */ + linkPathLen = readlinkat(directoryFd, entry->d_name, linkPath, PATH_MAX); + if (linkPathLen >= 0) { + linkPath[linkPathLen] = '\0'; + } + + linkLen = (linkPathLen >= 0) ? (jsize)linkPathLen : 0; + linkBytes = (*env)->NewByteArray(env, linkLen); + if (linkBytes == NULL) { + (*env)->DeleteLocalRef(env, statObject); + goto cleanup; + } + if (linkLen > 0) { + (*env)->SetByteArrayRegion(env, linkBytes, 0, linkLen, (const jbyte*)linkPath); + } + (*env)->SetObjectField(env, statObject, linkFieldId, linkBytes); + (*env)->DeleteLocalRef(env, linkBytes); + if ((*env)->ExceptionCheck(env)) { + (*env)->DeleteLocalRef(env, statObject); + goto cleanup; + } + } + + if (convertStatToObject(env, st, statErrno, statObject) != 0) { + (*env)->DeleteLocalRef(env, statObject); + goto cleanup; + } + + { + jbyteArray nameBytes; + jsize nameLen = (jsize)strlen(entry->d_name); + nameBytes = (*env)->NewByteArray(env, nameLen); + if (nameBytes == NULL) { + (*env)->DeleteLocalRef(env, statObject); + goto cleanup; + } + (*env)->SetByteArrayRegion(env, nameBytes, 0, nameLen, (const jbyte*)entry->d_name); + (*env)->SetObjectField(env, statObject, nameFieldId, nameBytes); + (*env)->DeleteLocalRef(env, nameBytes); + if ((*env)->ExceptionCheck(env)) { + (*env)->DeleteLocalRef(env, statObject); + goto cleanup; + } + } + + (*env)->SetObjectArrayElement(env, statArray, count, statObject); + if ((*env)->ExceptionCheck(env)) { + (*env)->DeleteLocalRef(env, statObject); + goto cleanup; + } + (*env)->DeleteLocalRef(env, statObject); + + count++; + } + + resultStatsArray = (*env)->NewObjectArray(env, count, LinuxStructStatClass, NULL); + if (resultStatsArray == NULL) { + goto cleanup; + } + + for (i = 0; i < count; i++) { + jobject existingStat = (*env)->GetObjectArrayElement(env, statArray, i); + if ((*env)->ExceptionCheck(env)) { + if (existingStat != NULL) { + (*env)->DeleteLocalRef(env, existingStat); + } + goto cleanup; + } + + (*env)->SetObjectArrayElement(env, resultStatsArray, i, existingStat); + (*env)->DeleteLocalRef(env, existingStat); + if ((*env)->ExceptionCheck(env)) { + goto cleanup; + } + } + + result = resultStatsArray; + resultStatsArray = NULL; + +cleanup: + if (dir != NULL) { + closedir(dir); + } + if (statArray != NULL) { + (*env)->DeleteLocalRef(env, statArray); + } + if (resultStatsArray != NULL) { + (*env)->DeleteLocalRef(env, resultStatsArray); + } + return result; +} \ No newline at end of file diff --git a/resources/bundles/org.eclipse.core.filesystem/natives/unix/fastlinux/fastlinuxfile.h b/resources/bundles/org.eclipse.core.filesystem/natives/unix/fastlinux/fastlinuxfile.h new file mode 100644 index 00000000000..ab59f9e5e85 --- /dev/null +++ b/resources/bundles/org.eclipse.core.filesystem/natives/unix/fastlinux/fastlinuxfile.h @@ -0,0 +1,105 @@ +/******************************************************************************* + * Copyright (c) 2010 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +#include + +/* + * Get a null-terminated byte array from a java byte array. The returned bytearray + * needs to be freed when not used anymore. Use free(result) to do that. + */ +jbyte* getByteArray(JNIEnv *, jbyteArray); + +/* + * Fills LinuxStructStat object with data from struct stat. + */ +jint convertStatToObject(JNIEnv *, struct stat, int errnoValue, jobject); + +/* DO NOT EDIT THIS FILE - it is machine generated */ + +/* Header for class org_eclipse_core_internal_filesystem_local_linux_LinuxFileNatives */ + +#ifndef _Included_org_eclipse_core_internal_filesystem_local_linux_LinuxFileNatives +#define _Included_org_eclipse_core_internal_filesystem_local_linux_LinuxFileNatives +#ifdef __cplusplus +extern "C" { +#endif +#undef org_eclipse_core_internal_filesystem_local_linux_LinuxFileNatives_ENOENT +#define org_eclipse_core_internal_filesystem_local_linux_LinuxFileNatives_ENOENT 2L +/* + * Class: org_eclipse_core_internal_filesystem_local_linux_LinuxFileNatives + * Method: initializeLinuxStructStatFieldIDs + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_org_eclipse_core_internal_filesystem_local_linux_LinuxFileNatives_initializeLinuxStructStatFieldIDs + (JNIEnv *, jclass); + +/* + * Class: org_eclipse_core_internal_filesystem_local_linux_LinuxFileNatives + * Method: chmod + * Signature: ([BI)I + */ +JNIEXPORT jint JNICALL Java_org_eclipse_core_internal_filesystem_local_linux_LinuxFileNatives_chmod + (JNIEnv *, jclass, jbyteArray, jint); + +/* + * Class: org_eclipse_core_internal_filesystem_local_linux_LinuxFileNatives + * Method: stat + * Signature: ([BLorg/eclipse/core/internal/filesystem/local/linux/LinuxStructStat;)I + */ +JNIEXPORT jint JNICALL Java_org_eclipse_core_internal_filesystem_local_linux_LinuxFileNatives_stat + (JNIEnv *, jclass, jbyteArray, jobject); + +/* + * Class: org_eclipse_core_internal_filesystem_local_linux_LinuxFileNatives + * Method: lstat + * Signature: ([BLorg/eclipse/core/internal/filesystem/local/linux/LinuxStructStat;)I + */ +JNIEXPORT jint JNICALL Java_org_eclipse_core_internal_filesystem_local_linux_LinuxFileNatives_lstat + (JNIEnv *, jclass, jbyteArray, jobject); + +/* + * Class: org_eclipse_core_internal_filesystem_local_linux_LinuxFileNatives + * Method: readlink + * Signature: ([B[BJ)I + */ +JNIEXPORT jint JNICALL Java_org_eclipse_core_internal_filesystem_local_linux_LinuxFileNatives_readlink + (JNIEnv *, jclass, jbyteArray, jbyteArray, jlong); + +/* + * Class: org_eclipse_core_internal_filesystem_local_linux_LinuxFileNatives + * Method: getflag + * Signature: ([B)I + */ +JNIEXPORT jint JNICALL Java_org_eclipse_core_internal_filesystem_local_linux_LinuxFileNatives_getflag + (JNIEnv *, jclass, jbyteArray); + +/* + * Class: org_eclipse_core_internal_filesystem_local_linux_LinuxFileNatives + * Method: listDir + * Signature: ([B)[[B + */ +JNIEXPORT jobjectArray JNICALL Java_org_eclipse_core_internal_filesystem_local_linux_LinuxFileNatives_listDir + (JNIEnv *, jclass, jbyteArray); + +/* + * Class: org_eclipse_core_internal_filesystem_local_linux_LinuxFileNatives + * Method: listDirAndGetFileInfos + * Signature: ([B)[Lorg/eclipse/core/internal/filesystem/local/linux/LinuxStructStat; + */ +JNIEXPORT jobjectArray JNICALL Java_org_eclipse_core_internal_filesystem_local_linux_LinuxFileNatives_listDirAndGetFileInfos + (JNIEnv *, jclass, jbyteArray); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/resources/bundles/org.eclipse.core.filesystem/src/org/eclipse/core/internal/filesystem/local/LocalFileNativesManager.java b/resources/bundles/org.eclipse.core.filesystem/src/org/eclipse/core/internal/filesystem/local/LocalFileNativesManager.java index 89ab0df082e..8a9fe40831f 100644 --- a/resources/bundles/org.eclipse.core.filesystem/src/org/eclipse/core/internal/filesystem/local/LocalFileNativesManager.java +++ b/resources/bundles/org.eclipse.core.filesystem/src/org/eclipse/core/internal/filesystem/local/LocalFileNativesManager.java @@ -18,6 +18,8 @@ import java.util.Set; import org.eclipse.core.filesystem.IFileInfo; import org.eclipse.core.filesystem.provider.FileInfo; +import org.eclipse.core.internal.filesystem.local.linux.LinuxFileHandler; +import org.eclipse.core.internal.filesystem.local.linux.LinuxFileNatives; import org.eclipse.core.internal.filesystem.local.nio.DefaultHandler; import org.eclipse.core.internal.filesystem.local.nio.PosixHandler; import org.eclipse.core.internal.filesystem.local.unix.UnixFileHandler; @@ -38,7 +40,9 @@ */ public class LocalFileNativesManager { public static final boolean PROPERTY_USE_NATIVE_DEFAULT = true; + public static final boolean PROPERTY_USE_FAST_LINUX_NATIVES_DEFAULT = true; public static final String PROPERTY_USE_NATIVES = "eclipse.filesystem.useNatives"; //$NON-NLS-1$ + public static final String PROPERTY_USE_FAST_LINUX_NATIVES = "eclipse.filesystem.useFastLinuxNatives"; //$NON-NLS-1$ private static NativeHandler HANDLER; static { @@ -49,16 +53,21 @@ public class LocalFileNativesManager { * reset the usage of native to the system default */ public static void reset() { - setUsingNative(Boolean.parseBoolean(System.getProperty(PROPERTY_USE_NATIVES, String.valueOf(PROPERTY_USE_NATIVE_DEFAULT)))); + setUsingNative(Boolean.parseBoolean(System.getProperty(PROPERTY_USE_NATIVES, String.valueOf(PROPERTY_USE_NATIVE_DEFAULT))), + Boolean.parseBoolean(System.getProperty(PROPERTY_USE_FAST_LINUX_NATIVES, String.valueOf(PROPERTY_USE_FAST_LINUX_NATIVES_DEFAULT)))); } /** * Try to set the usage of natives to the provided value * @return true if natives are used as result of this call false otherwise */ - public static boolean setUsingNative(boolean useNatives) { + public static boolean setUsingNative(boolean useNatives, boolean useFastLinuxNatives) { boolean nativesAreUsed; - if (useNatives && !Platform.OS.isWindows() && UnixFileNatives.isUsingNatives()) { + if (useNatives && useFastLinuxNatives && Platform.OS.isLinux() && Platform.ARCH_X86_64.equals(Platform.getOSArch()) && LinuxFileNatives.isUsingNatives()) { + // Linux x86_64 architecture supports faster (bulk) file info fetching. + HANDLER = new LinuxFileHandler(); + nativesAreUsed = true; + } else if (useNatives && !Platform.OS.isWindows() && UnixFileNatives.isUsingNatives()) { HANDLER = new UnixFileHandler(); nativesAreUsed = true; } else { diff --git a/resources/bundles/org.eclipse.core.filesystem/src/org/eclipse/core/internal/filesystem/local/linux/LinuxFileFlags.java b/resources/bundles/org.eclipse.core.filesystem/src/org/eclipse/core/internal/filesystem/local/linux/LinuxFileFlags.java new file mode 100644 index 00000000000..8cb5fc5cbfc --- /dev/null +++ b/resources/bundles/org.eclipse.core.filesystem/src/org/eclipse/core/internal/filesystem/local/linux/LinuxFileFlags.java @@ -0,0 +1,88 @@ +/******************************************************************************* + * Copyright (c) 2010 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.core.internal.filesystem.local.linux; + +public class LinuxFileFlags { + + static { + PATH_MAX = LinuxFileNatives.getFlag("PATH_MAX"); //$NON-NLS-1$ + S_IFMT = LinuxFileNatives.getFlag("S_IFMT"); //$NON-NLS-1$ + S_IFLNK = LinuxFileNatives.getFlag("S_IFLNK"); //$NON-NLS-1$ + S_IFDIR = LinuxFileNatives.getFlag("S_IFDIR"); //$NON-NLS-1$ + S_IRUSR = LinuxFileNatives.getFlag("S_IRUSR"); //$NON-NLS-1$ + S_IWUSR = LinuxFileNatives.getFlag("S_IWUSR"); //$NON-NLS-1$ + S_IXUSR = LinuxFileNatives.getFlag("S_IXUSR"); //$NON-NLS-1$ + S_IRGRP = LinuxFileNatives.getFlag("S_IRGRP"); //$NON-NLS-1$ + S_IWGRP = LinuxFileNatives.getFlag("S_IWGRP"); //$NON-NLS-1$ + S_IXGRP = LinuxFileNatives.getFlag("S_IXGRP"); //$NON-NLS-1$ + S_IROTH = LinuxFileNatives.getFlag("S_IROTH"); //$NON-NLS-1$ + S_IWOTH = LinuxFileNatives.getFlag("S_IWOTH"); //$NON-NLS-1$ + S_IXOTH = LinuxFileNatives.getFlag("S_IXOTH"); //$NON-NLS-1$ + } + + /** + * chars in a path name including nul + */ + public static final int PATH_MAX; + + /** + * bitmask for the file type bitfields + */ + public static final int S_IFMT; + /** + * symbolic link + */ + public static final int S_IFLNK; + /** + * directory + */ + public static final int S_IFDIR; + /** + * owner has read permission + */ + public static final int S_IRUSR; + /** + * owner has write permission + */ + public static final int S_IWUSR; + /** + * owner has execute permission + */ + public static final int S_IXUSR; + /** + * group has read permission + */ + public static final int S_IRGRP; + /** + * group has write permission + */ + public static final int S_IWGRP; + /** + * group has execute permission + */ + public static final int S_IXGRP; + /** + * others have read permission + */ + public static final int S_IROTH; + /** + * others have write permission + */ + public static final int S_IWOTH; + /** + * others have execute permission + */ + public static final int S_IXOTH; + +} diff --git a/resources/bundles/org.eclipse.core.filesystem/src/org/eclipse/core/internal/filesystem/local/linux/LinuxFileHandler.java b/resources/bundles/org.eclipse.core.filesystem/src/org/eclipse/core/internal/filesystem/local/linux/LinuxFileHandler.java new file mode 100644 index 00000000000..d739286efcd --- /dev/null +++ b/resources/bundles/org.eclipse.core.filesystem/src/org/eclipse/core/internal/filesystem/local/linux/LinuxFileHandler.java @@ -0,0 +1,48 @@ +/******************************************************************************* + * Copyright (c) 2012, 2015 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.core.internal.filesystem.local.linux; + +import org.eclipse.core.filesystem.IFileInfo; +import org.eclipse.core.filesystem.provider.FileInfo; +import org.eclipse.core.internal.filesystem.local.NativeHandler; + +/** + * Native handler that delegates to LinuxFileNatives + */ +public class LinuxFileHandler extends NativeHandler { + @Override + public int getSupportedAttributes() { + return LinuxFileNatives.getSupportedAttributes(); + } + + @Override + public FileInfo fetchFileInfo(String fileName) { + return LinuxFileNatives.fetchFileInfo(fileName); + } + + @Override + public boolean putFileInfo(String fileName, IFileInfo info, int options) { + return LinuxFileNatives.putFileInfo(fileName, info, options); + } + + @Override + public String[] listDirectoryNames(String fileName) { + return LinuxFileNatives.listDirectoryNames(fileName); + } + + @Override + public IFileInfo[] listDirectoryAndGetFileInfos(String fileName) { + return LinuxFileNatives.listDirectoryAndGetFileInfos(fileName); + } +} diff --git a/resources/bundles/org.eclipse.core.filesystem/src/org/eclipse/core/internal/filesystem/local/linux/LinuxFileNatives.java b/resources/bundles/org.eclipse.core.filesystem/src/org/eclipse/core/internal/filesystem/local/linux/LinuxFileNatives.java new file mode 100644 index 00000000000..a50462736e2 --- /dev/null +++ b/resources/bundles/org.eclipse.core.filesystem/src/org/eclipse/core/internal/filesystem/local/linux/LinuxFileNatives.java @@ -0,0 +1,234 @@ +/******************************************************************************* + * Copyright (c) 2010, 2017 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + * Sergey Prigogin (Google) - ongoing development + *******************************************************************************/ +package org.eclipse.core.internal.filesystem.local.linux; + +import static org.eclipse.core.internal.filesystem.local.linux.LinuxFileFlags.PATH_MAX; +import static org.eclipse.core.internal.filesystem.local.linux.LinuxFileFlags.S_IFLNK; +import static org.eclipse.core.internal.filesystem.local.linux.LinuxFileFlags.S_IFMT; +import static org.eclipse.core.internal.filesystem.local.linux.LinuxFileFlags.S_IRGRP; +import static org.eclipse.core.internal.filesystem.local.linux.LinuxFileFlags.S_IROTH; +import static org.eclipse.core.internal.filesystem.local.linux.LinuxFileFlags.S_IRUSR; +import static org.eclipse.core.internal.filesystem.local.linux.LinuxFileFlags.S_IWGRP; +import static org.eclipse.core.internal.filesystem.local.linux.LinuxFileFlags.S_IWOTH; +import static org.eclipse.core.internal.filesystem.local.linux.LinuxFileFlags.S_IWUSR; +import static org.eclipse.core.internal.filesystem.local.linux.LinuxFileFlags.S_IXGRP; +import static org.eclipse.core.internal.filesystem.local.linux.LinuxFileFlags.S_IXOTH; +import static org.eclipse.core.internal.filesystem.local.linux.LinuxFileFlags.S_IXUSR; + +import java.io.File; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.util.Enumeration; +import org.eclipse.core.filesystem.EFS; +import org.eclipse.core.filesystem.IFileInfo; +import org.eclipse.core.filesystem.provider.FileInfo; +import org.eclipse.core.internal.filesystem.FileSystemAccess; +import org.eclipse.core.internal.filesystem.Messages; +import org.eclipse.core.internal.filesystem.Policy; +import org.eclipse.core.internal.filesystem.local.Convert; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.osgi.util.NLS; + +public abstract class LinuxFileNatives { + private static final String LIBRARY_NAME = "fastlinuxfile_1_0_0"; //$NON-NLS-1$ + private static final int ENOENT = LinuxStructStat.ENOENT; // errno value for "No such file or directory" + + private static final boolean usingNatives; + protected static final String[] EMPTY_STRING_ARRAY = {}; + + static { + boolean _usingNatives = false; + try { + System.loadLibrary(LIBRARY_NAME); + _usingNatives = true; + initializeLinuxStructStatFieldIDs(); + } catch (UnsatisfiedLinkError e) { + if (isLibraryPresent()) { + logMissingNativeLibrary(e); + } + } finally { + usingNatives = _usingNatives; + } + } + + private static boolean isLibraryPresent() { + String libName = System.mapLibraryName(LIBRARY_NAME); + Enumeration entries = FileSystemAccess.findEntries("/", libName, true); //$NON-NLS-1$ + return entries != null && entries.hasMoreElements(); + } + + private static void logMissingNativeLibrary(UnsatisfiedLinkError e) { + String libName = System.mapLibraryName(LIBRARY_NAME); + String message = NLS.bind(Messages.couldNotLoadLibrary, libName); + Policy.log(IStatus.INFO, message, e); + } + + public static int getSupportedAttributes() { + if (!usingNatives) { + return -1; + } + int ret = EFS.ATTRIBUTE_READ_ONLY | EFS.ATTRIBUTE_EXECUTABLE | EFS.ATTRIBUTE_SYMLINK | EFS.ATTRIBUTE_LINK_TARGET | EFS.ATTRIBUTE_OWNER_READ | EFS.ATTRIBUTE_OWNER_WRITE | EFS.ATTRIBUTE_OWNER_EXECUTE | EFS.ATTRIBUTE_GROUP_READ | EFS.ATTRIBUTE_GROUP_WRITE | EFS.ATTRIBUTE_GROUP_EXECUTE | EFS.ATTRIBUTE_OTHER_READ | EFS.ATTRIBUTE_OTHER_WRITE | EFS.ATTRIBUTE_OTHER_EXECUTE; + return ret; + } + + public static String[] listDirectoryNames(String pathName) { + byte[] name = fileNameToBytes(pathName); + byte[][] result = listDir(name); + if (result == null) { + return EMPTY_STRING_ARRAY; + } + String[] names = new String[result.length]; + for (int i = 0; i < result.length; i++) { + names[i] = Convert.fromPlatformBytes(result[i], result[i].length); + } + return names; + } + + public static IFileInfo[] listDirectoryAndGetFileInfos(String pathName) { + byte[] name = fileNameToBytes(pathName); + LinuxStructStat[] stats = listDirAndGetFileInfos(name); + if (stats == null) { + return new IFileInfo[0]; + } + int count = stats.length; + IFileInfo[] infos = new IFileInfo[count]; + for (int i = 0; i < count; i++) { + var st = stats[i].toFileInfo(); + infos[i] = st; + } + return infos; + } + + public static FileInfo fetchFileInfo(String fileName) { + FileInfo info = null; + byte[] name = fileNameToBytes(fileName); + LinuxStructStat stat = new LinuxStructStat(); + if (lstat(name, stat) == 0 || stat.errno == ENOENT) { // lstat fills errno even on failure + if (stat.errno == ENOENT) { + // file does not exist + info = new FileInfo(); + } else if ((stat.st_mode & S_IFMT) == S_IFLNK) { // it's a link! + LinuxStructStat targetStat = new LinuxStructStat(); + if (stat(name, targetStat) == 0) { // get the information about the file the link points to + info = targetStat.toFileInfo(); // store the target file stats in info + } else { // invalid link target + info = new FileInfo(); + if (targetStat.errno != ENOENT) { + info.setError(IFileInfo.IO_ERROR); + } + } + info.setAttribute(EFS.ATTRIBUTE_SYMLINK, true); // set symlink attribute + byte target[] = new byte[PATH_MAX]; + int length = readlink(name, target, target.length); + if (length > 0) { // set target of the link + info.setStringAttribute(EFS.ATTRIBUTE_LINK_TARGET, bytesToFileName(target, length)); + } + } else { // regular file or directory + info = stat.toFileInfo(); + } + } else { + info = new FileInfo(); + if (stat.errno != ENOENT) { + info.setError(IFileInfo.IO_ERROR); + } + } + + if (info.getName().isEmpty()) { + // If the file system is case insensitive, we don't know the real name of the file. + // Since obtaining the real name in such situation is pretty expensive, we use the name + // passed as a parameter, which may differ by case from the real name of the file + // if the file system is case insensitive. + info.setName(new File(fileName).getName()); + } + return info; + } + + public static boolean putFileInfo(String fileName, IFileInfo info, int options) { + int code = 0; + byte[] name = fileNameToBytes(fileName); + if (name == null) { + return false; + } + + // Change permissions + int mode = 0; + if (info.getAttribute(EFS.ATTRIBUTE_OWNER_READ)) { + mode |= S_IRUSR; + } + if (info.getAttribute(EFS.ATTRIBUTE_OWNER_WRITE)) { + mode |= S_IWUSR; + } + if (info.getAttribute(EFS.ATTRIBUTE_OWNER_EXECUTE)) { + mode |= S_IXUSR; + } + if (info.getAttribute(EFS.ATTRIBUTE_GROUP_READ)) { + mode |= S_IRGRP; + } + if (info.getAttribute(EFS.ATTRIBUTE_GROUP_WRITE)) { + mode |= S_IWGRP; + } + if (info.getAttribute(EFS.ATTRIBUTE_GROUP_EXECUTE)) { + mode |= S_IXGRP; + } + if (info.getAttribute(EFS.ATTRIBUTE_OTHER_READ)) { + mode |= S_IROTH; + } + if (info.getAttribute(EFS.ATTRIBUTE_OTHER_WRITE)) { + mode |= S_IWOTH; + } + if (info.getAttribute(EFS.ATTRIBUTE_OTHER_EXECUTE)) { + mode |= S_IXOTH; + } + code |= chmod(name, mode); + + return code == 0; + } + + public static boolean isUsingNatives() { + return usingNatives; + } + + public static int getFlag(String flag) { + if (!usingNatives) { + return -1; + } + return getflag(flag.getBytes(StandardCharsets.US_ASCII)); + } + + private static byte[] fileNameToBytes(String fileName) { + return Convert.toPlatformBytes(fileName); + } + + private static String bytesToFileName(byte[] buf, int length) { + return Convert.fromPlatformBytes(buf, length); + } + + private static final native void initializeLinuxStructStatFieldIDs(); + + private static final native int chmod(byte[] path, int mode); + + private static final native int stat(byte[] path, LinuxStructStat buf); + + private static final native int lstat(byte[] path, LinuxStructStat buf); + + private static final native int readlink(byte[] path, byte[] buf, long bufsiz); + + private static final native int getflag(byte[] buf); + + private static final native byte[][] listDir(byte[] path); + + private static final native LinuxStructStat[] listDirAndGetFileInfos(byte[] path); + +} diff --git a/resources/bundles/org.eclipse.core.filesystem/src/org/eclipse/core/internal/filesystem/local/linux/LinuxStructStat.java b/resources/bundles/org.eclipse.core.filesystem/src/org/eclipse/core/internal/filesystem/local/linux/LinuxStructStat.java new file mode 100644 index 00000000000..09da16f50e5 --- /dev/null +++ b/resources/bundles/org.eclipse.core.filesystem/src/org/eclipse/core/internal/filesystem/local/linux/LinuxStructStat.java @@ -0,0 +1,94 @@ +/******************************************************************************* + * Copyright (c) 2010 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.core.internal.filesystem.local.linux; + +import org.eclipse.core.filesystem.EFS; +import org.eclipse.core.filesystem.IFileInfo; +import org.eclipse.core.filesystem.provider.FileInfo; +import org.eclipse.core.internal.filesystem.local.Convert; + +/** + * This class mirrors relevant fields of native struct stat + * and is used by JNI calls wrapping OS file related functions. + */ +public class LinuxStructStat { + /** errno value for "No such file or directory" */ + public static final int ENOENT = 2; + + private static final boolean USE_MILLISECOND_RESOLUTION = Boolean.parseBoolean(System.getProperty("eclipse.filesystem.useNatives.modificationTimestampMillisecondsResolution", "true")); //$NON-NLS-1$ //$NON-NLS-2$ + + public int st_mode; + public long st_size; + public long st_mtime; + public long st_mtime_msec; // millisecond component of the file timestamp + public int errno; + public byte[] name; + public byte[] linkFile; // Filled target for symbolic links + + public FileInfo toFileInfo() { + FileInfo info = new FileInfo(); + if (name != null) { + info.setName(Convert.fromPlatformBytes(name, name.length)); + } + if (errno != 0 && errno != ENOENT) { + info.setError(IFileInfo.IO_ERROR); + return info; + } + info.setExists(errno != ENOENT); + info.setLength(st_size); + long lastModified = (st_mtime * 1_000); + if (USE_MILLISECOND_RESOLUTION) { + lastModified += st_mtime_msec; + } + info.setLastModified(lastModified); + if ((st_mode & LinuxFileFlags.S_IFMT) == LinuxFileFlags.S_IFDIR) { + info.setDirectory(true); + } + if (linkFile != null) { + info.setAttribute(EFS.ATTRIBUTE_SYMLINK, true); + if (linkFile.length > 0) { + info.setStringAttribute(EFS.ATTRIBUTE_LINK_TARGET, Convert.fromPlatformBytes(linkFile, linkFile.length)); + } + } + if ((st_mode & LinuxFileFlags.S_IRUSR) == 0) { // Set to true in FileInfo constructor + info.setAttribute(EFS.ATTRIBUTE_OWNER_READ, false); + } + if ((st_mode & LinuxFileFlags.S_IWUSR) == 0) { // Set to true in FileInfo constructor + info.setAttribute(EFS.ATTRIBUTE_OWNER_WRITE, false); + } + if ((st_mode & LinuxFileFlags.S_IXUSR) != 0) { + info.setAttribute(EFS.ATTRIBUTE_OWNER_EXECUTE, true); + } + if ((st_mode & LinuxFileFlags.S_IRGRP) != 0) { + info.setAttribute(EFS.ATTRIBUTE_GROUP_READ, true); + } + if ((st_mode & LinuxFileFlags.S_IWGRP) != 0) { + info.setAttribute(EFS.ATTRIBUTE_GROUP_WRITE, true); + } + if ((st_mode & LinuxFileFlags.S_IXGRP) != 0) { + info.setAttribute(EFS.ATTRIBUTE_GROUP_EXECUTE, true); + } + if ((st_mode & LinuxFileFlags.S_IROTH) != 0) { + info.setAttribute(EFS.ATTRIBUTE_OTHER_READ, true); + } + if ((st_mode & LinuxFileFlags.S_IWOTH) != 0) { + info.setAttribute(EFS.ATTRIBUTE_OTHER_WRITE, true); + } + if ((st_mode & LinuxFileFlags.S_IXOTH) != 0) { + info.setAttribute(EFS.ATTRIBUTE_OTHER_EXECUTE, true); + } + return info; + } + +} diff --git a/resources/bundles/org.eclipse.core.filesystem/src/org/eclipse/core/internal/filesystem/local/unix/StructStat.java b/resources/bundles/org.eclipse.core.filesystem/src/org/eclipse/core/internal/filesystem/local/unix/StructStat.java index 598575ab16f..22dbf3573d7 100644 --- a/resources/bundles/org.eclipse.core.filesystem/src/org/eclipse/core/internal/filesystem/local/unix/StructStat.java +++ b/resources/bundles/org.eclipse.core.filesystem/src/org/eclipse/core/internal/filesystem/local/unix/StructStat.java @@ -14,7 +14,6 @@ package org.eclipse.core.internal.filesystem.local.unix; import org.eclipse.core.filesystem.EFS; -import org.eclipse.core.filesystem.IFileInfo; import org.eclipse.core.filesystem.provider.FileInfo; /** @@ -32,20 +31,10 @@ public class StructStat { public long st_mtime; public long st_mtime_msec; // millisecond component of the file timestamp, filled on Linux systems public long st_flags; // Filled only on Mac OS X - public int errno; - public String name; - public String linkFile; // Filled target for symbolic links public FileInfo toFileInfo() { FileInfo info = new FileInfo(); - if (errno != 0 && errno != ENOENT) { - info.setError(IFileInfo.IO_ERROR); - return info; - } - info.setExists(errno != ENOENT); - if (name != null) { - info.setName(name); - } + info.setExists(true); info.setLength(st_size); long lastModified = (st_mtime * 1_000); if (USE_MILLISECOND_RESOLUTION) { @@ -55,12 +44,6 @@ public FileInfo toFileInfo() { if ((st_mode & UnixFileFlags.S_IFMT) == UnixFileFlags.S_IFDIR) { info.setDirectory(true); } - if (linkFile != null) { - info.setAttribute(EFS.ATTRIBUTE_SYMLINK, true); - if (!linkFile.isEmpty()) { - info.setStringAttribute(EFS.ATTRIBUTE_LINK_TARGET, linkFile); - } - } if ((st_flags & (UnixFileFlags.UF_IMMUTABLE | UnixFileFlags.SF_IMMUTABLE)) != 0) { info.setAttribute(EFS.ATTRIBUTE_IMMUTABLE, true); } diff --git a/resources/bundles/org.eclipse.core.filesystem/src/org/eclipse/core/internal/filesystem/local/unix/UnixFileNatives.java b/resources/bundles/org.eclipse.core.filesystem/src/org/eclipse/core/internal/filesystem/local/unix/UnixFileNatives.java index ddb3cc9a947..c69c79b2421 100644 --- a/resources/bundles/org.eclipse.core.filesystem/src/org/eclipse/core/internal/filesystem/local/unix/UnixFileNatives.java +++ b/resources/bundles/org.eclipse.core.filesystem/src/org/eclipse/core/internal/filesystem/local/unix/UnixFileNatives.java @@ -14,6 +14,21 @@ *******************************************************************************/ package org.eclipse.core.internal.filesystem.local.unix; +import static org.eclipse.core.internal.filesystem.local.unix.UnixFileFlags.PATH_MAX; +import static org.eclipse.core.internal.filesystem.local.unix.UnixFileFlags.SF_IMMUTABLE; +import static org.eclipse.core.internal.filesystem.local.unix.UnixFileFlags.S_IFLNK; +import static org.eclipse.core.internal.filesystem.local.unix.UnixFileFlags.S_IFMT; +import static org.eclipse.core.internal.filesystem.local.unix.UnixFileFlags.S_IRGRP; +import static org.eclipse.core.internal.filesystem.local.unix.UnixFileFlags.S_IROTH; +import static org.eclipse.core.internal.filesystem.local.unix.UnixFileFlags.S_IRUSR; +import static org.eclipse.core.internal.filesystem.local.unix.UnixFileFlags.S_IWGRP; +import static org.eclipse.core.internal.filesystem.local.unix.UnixFileFlags.S_IWOTH; +import static org.eclipse.core.internal.filesystem.local.unix.UnixFileFlags.S_IWUSR; +import static org.eclipse.core.internal.filesystem.local.unix.UnixFileFlags.S_IXGRP; +import static org.eclipse.core.internal.filesystem.local.unix.UnixFileFlags.S_IXOTH; +import static org.eclipse.core.internal.filesystem.local.unix.UnixFileFlags.S_IXUSR; +import static org.eclipse.core.internal.filesystem.local.unix.UnixFileFlags.UF_IMMUTABLE; + import java.io.File; import java.net.URL; import java.nio.charset.StandardCharsets; @@ -83,7 +98,7 @@ public static FileInfo fetchFileInfo(String fileName) { byte[] name = fileNameToBytes(fileName); StructStat stat = new StructStat(); if (lstat(name, stat) == 0) { // return information about the link itself if the file is a symbolic link - if ((stat.st_mode & UnixFileFlags.S_IFMT) == UnixFileFlags.S_IFLNK) { // it a link! + if ((stat.st_mode & S_IFMT) == S_IFLNK) { // it a link! if (stat(name, stat) == 0) { // get the information about the file the link points to info = stat.toFileInfo(); // store the target file stats in info } else { // invalid link target! @@ -93,7 +108,7 @@ public static FileInfo fetchFileInfo(String fileName) { } } info.setAttribute(EFS.ATTRIBUTE_SYMLINK, true); // set symlink attribute - byte target[] = new byte[UnixFileFlags.PATH_MAX]; + byte target[] = new byte[PATH_MAX]; int length = readlink(name, target, target.length); if (length > 0) { // set target of the link info.setStringAttribute(EFS.ATTRIBUTE_LINK_TARGET, bytesToFileName(target, length)); @@ -131,8 +146,8 @@ public static boolean putFileInfo(String fileName, IFileInfo info, int options) StructStat stat = new StructStat(); if (stat(name, stat) == 0) { long flags = stat.st_flags; - flags &= ~UnixFileFlags.SF_IMMUTABLE; - flags &= ~UnixFileFlags.UF_IMMUTABLE; + flags &= ~SF_IMMUTABLE; + flags &= ~UF_IMMUTABLE; code |= chflags(name, (int) flags); } } @@ -140,31 +155,31 @@ public static boolean putFileInfo(String fileName, IFileInfo info, int options) // Change permissions int mode = 0; if (info.getAttribute(EFS.ATTRIBUTE_OWNER_READ)) { - mode |= UnixFileFlags.S_IRUSR; + mode |= S_IRUSR; } if (info.getAttribute(EFS.ATTRIBUTE_OWNER_WRITE)) { - mode |= UnixFileFlags.S_IWUSR; + mode |= S_IWUSR; } if (info.getAttribute(EFS.ATTRIBUTE_OWNER_EXECUTE)) { - mode |= UnixFileFlags.S_IXUSR; + mode |= S_IXUSR; } if (info.getAttribute(EFS.ATTRIBUTE_GROUP_READ)) { - mode |= UnixFileFlags.S_IRGRP; + mode |= S_IRGRP; } if (info.getAttribute(EFS.ATTRIBUTE_GROUP_WRITE)) { - mode |= UnixFileFlags.S_IWGRP; + mode |= S_IWGRP; } if (info.getAttribute(EFS.ATTRIBUTE_GROUP_EXECUTE)) { - mode |= UnixFileFlags.S_IXGRP; + mode |= S_IXGRP; } if (info.getAttribute(EFS.ATTRIBUTE_OTHER_READ)) { - mode |= UnixFileFlags.S_IROTH; + mode |= S_IROTH; } if (info.getAttribute(EFS.ATTRIBUTE_OTHER_WRITE)) { - mode |= UnixFileFlags.S_IWOTH; + mode |= S_IWOTH; } if (info.getAttribute(EFS.ATTRIBUTE_OTHER_EXECUTE)) { - mode |= UnixFileFlags.S_IXOTH; + mode |= S_IXOTH; } code |= chmod(name, mode); @@ -173,7 +188,7 @@ public static boolean putFileInfo(String fileName, IFileInfo info, int options) StructStat stat = new StructStat(); if (stat(name, stat) == 0) { long flags = stat.st_flags; - flags |= UnixFileFlags.UF_IMMUTABLE; + flags |= UF_IMMUTABLE; code |= chflags(name, (int) flags); } } diff --git a/resources/tests/org.eclipse.core.tests.resources/src/org/eclipse/core/tests/resources/perf/BenchFileStore.java b/resources/tests/org.eclipse.core.tests.resources/src/org/eclipse/core/tests/resources/perf/BenchFileStore.java index 2ace865f6dd..bc469137c09 100644 --- a/resources/tests/org.eclipse.core.tests.resources/src/org/eclipse/core/tests/resources/perf/BenchFileStore.java +++ b/resources/tests/org.eclipse.core.tests.resources/src/org/eclipse/core/tests/resources/perf/BenchFileStore.java @@ -22,6 +22,7 @@ import org.eclipse.core.filesystem.IFileStore; import org.eclipse.core.internal.filesystem.local.LocalFileNativesManager; import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.Platform; import org.eclipse.core.tests.harness.PerformanceTestRunner; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -81,22 +82,40 @@ protected void test() { @Test public void testStoreExitsNative() throws Throwable{ - withNatives(true, () -> { + withNatives(true, false, () -> { new StoreTestRunner(true).run(getClass(), testInfo.getDisplayName(), REPEATS, LOOP_SIZE); }); } + @Test + public void testStoreExitsNative_Linux() throws Throwable { + if (Platform.OS.isLinux() && Platform.ARCH_X86_64.equals(Platform.getOSArch())) { + withNatives(true, true, () -> { + new StoreTestRunner(true).run(getClass(), testInfo.getDisplayName(), REPEATS, LOOP_SIZE); + }); + } + } + @Test public void testStoreNotExitsNative() throws Throwable { - withNatives(true, () -> { + withNatives(true, false, () -> { new StoreTestRunner(false).run(getClass(), testInfo.getDisplayName(), REPEATS, LOOP_SIZE); }); } + @Test + public void testStoreNotExitsNative_Linux() throws Throwable { + if (Platform.OS.isLinux() && Platform.ARCH_X86_64.equals(Platform.getOSArch())) { + withNatives(true, true, () -> { + new StoreTestRunner(false).run(getClass(), testInfo.getDisplayName(), REPEATS, LOOP_SIZE); + }); + } + } + @Test public void testStoreExitsNio() throws Throwable { - withNatives(false, () -> { + withNatives(false, false, () -> { new StoreTestRunner(true).run(getClass(), testInfo.getDisplayName(), REPEATS, LOOP_SIZE); }); @@ -104,14 +123,15 @@ public void testStoreExitsNio() throws Throwable { @Test public void testStoreNotExitsNio() throws Throwable { - withNatives(false, () -> { + withNatives(false, false, () -> { new StoreTestRunner(false).run(getClass(), testInfo.getDisplayName(), REPEATS, LOOP_SIZE); }); } - private static void withNatives(boolean natives, Executable runnable) throws Throwable { + private static void withNatives(boolean natives, boolean useFastLinuxNatives, Executable runnable) + throws Throwable { try { - assertEquals(natives, LocalFileNativesManager.setUsingNative(natives), + assertEquals(natives, LocalFileNativesManager.setUsingNative(natives, useFastLinuxNatives), "can't set natives to the desired value"); runnable.execute(); } finally {