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/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 00000000000..dcb1925e3a6
Binary files /dev/null and b/resources/bundles/org.eclipse.core.filesystem.linux.x86_64/os/linux/x86_64/libfastlinuxfile_1_0_0.so differ
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..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
-->
@@ -18,7 +18,7 @@
../../
org.eclipse.core.filesystem.linux.x86_64
- 1.2.400-SNAPSHOT
+ 1.2.500-SNAPSHOT
eclipse-plugin
@@ -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/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
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 {