### Eclipse Workspace Patch 1.0 #P org.eclipse.core.filesystem Index: natives/macosx/Makefile =================================================================== RCS file: natives/macosx/Makefile diff -N natives/macosx/Makefile --- natives/macosx/Makefile 22 Oct 2009 11:21:03 -0000 1.5 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,18 +0,0 @@ -#********************************************************************** -# Copyright (c) 2000, 2009 IBM Corporation and others. -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Eclipse Public License v1.0 -# which accompanies this distribution, and is available at -# http://www.eclipse.org/legal/epl-v10.html -#********************************************************************** -# -# makefile for libcore on MacOS X - - -LIB_NAME = liblocalfile_1_0_0.jnilib - -core: - cc -I /System/Library/Frameworks/JavaVM.framework/Headers localfile.c -o $(LIB_NAME) -bundle -framework JavaVM -framework CoreServices -arch i386 -arch ppc -arch x86_64 -mmacosx-version-min=10.4 - -clean: - rm *.jnilib Index: natives/macosx/localfile.c =================================================================== RCS file: natives/macosx/localfile.c diff -N natives/macosx/localfile.c --- natives/macosx/localfile.c 16 Dec 2009 11:59:58 -0000 1.7 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,425 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2000, 2009 IBM Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * IBM Corporation - initial API and implementation - * Andre Weinand (OTI Labs) - *******************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include - -#include "../localfile.h" - -#include - -#define USE_IMMUTABLE_FLAG 1 -#define USE_ARCHIVE_FLAG 0 -#define EFS_SYMLINK_SUPPORT 1 - -mode_t process_umask; - -/* - * Get a null-terminated byte array from a java char array. - * The byte array contains UTF8 encoding. - * The returned bytearray needs to be freed when not used - * anymore. Use free(result) to do that. - */ -static jbyte* getUTF8ByteArray(JNIEnv *env, jcharArray target) { - - jchar *temp= (*env)->GetCharArrayElements(env, target, 0); - jsize n= (*env)->GetArrayLength(env, target); - - CFStringRef sr= CFStringCreateWithCharacters(kCFAllocatorDefault, temp, n); - CFIndex argStringSize= CFStringGetMaximumSizeForEncoding(n, kCFStringEncodingUTF8) + 1; - jbyte *result= (jbyte*) calloc(argStringSize, sizeof(jbyte)); - CFStringGetCString(sr, (char*) result, argStringSize, kCFStringEncodingUTF8); - CFRelease(sr); - - (*env)->ReleaseCharArrayElements(env, target, temp, 0); - - return result; -} - -/* - * Class: org_eclipse_core_internal_filesystem_local_LocalFileNatives - * Method: nativeAttributes - * Signature: ()I - */ -JNIEXPORT jint JNICALL Java_org_eclipse_core_internal_filesystem_local_LocalFileNatives_nativeAttributes - (JNIEnv *env, jclass clazz) { -#if defined(EFS_SYMLINK_SUPPORT) - return ATTRIBUTE_READ_ONLY | ATTRIBUTE_EXECUTABLE | ATTRIBUTE_SYMLINK | ATTRIBUTE_LINK_TARGET; -#else - return ATTRIBUTE_READ_ONLY | ATTRIBUTE_EXECUTABLE; -#endif -} - -/* - * Class: org_eclipse_core_internal_filesystem_local_LocalFileNatives - * Method: internalIsUnicode - * Signature: ()Z - */ -JNIEXPORT jboolean JNICALL Java_org_eclipse_core_internal_filesystem_local_LocalFileNatives_internalIsUnicode - (JNIEnv *env, jclass clazz) { - return JNI_TRUE; // MacOS X supports Unicode-based file names in UTF-8 encoding -} - -/* - * Converts a stat structure to IFileInfo - */ -jboolean convertStatToFileInfo (JNIEnv *env, struct stat info, jobject fileInfo) { - jclass cls; - jmethodID mid; - jboolean readOnly; - - cls = (*env)->GetObjectClass(env, fileInfo); - if (cls == 0) return JNI_FALSE; - - // select interesting information - //exists - mid = (*env)->GetMethodID(env, cls, "setExists", "(Z)V"); - if (mid == 0) return JNI_FALSE; - (*env)->CallVoidMethod(env, fileInfo, mid, JNI_TRUE); - - // last modified - mid = (*env)->GetMethodID(env, cls, "setLastModified", "(J)V"); - if (mid == 0) return JNI_FALSE; - (*env)->CallVoidMethod(env, fileInfo, mid, ((jlong) info.st_mtime) * 1000); /* lower bits */ - - // file length - mid = (*env)->GetMethodID(env, cls, "setLength", "(J)V"); - if (mid == 0) return JNI_FALSE; - (*env)->CallVoidMethod(env, fileInfo, mid, (jlong)info.st_size); - - // folder or file? - if (S_ISDIR(info.st_mode)) { - mid = (*env)->GetMethodID(env, cls, "setAttribute", "(IZ)V"); - if (mid == 0) return JNI_FALSE; - (*env)->CallVoidMethod(env, fileInfo, mid, ATTRIBUTE_DIRECTORY, JNI_TRUE); - } - - // read-only? - readOnly = (info.st_mode & S_IWRITE) != S_IWRITE; -#if USE_IMMUTABLE_FLAG - if (!readOnly && ((info.st_flags & (UF_IMMUTABLE | SF_IMMUTABLE)) != 0)) - readOnly = true; -#endif - if (readOnly) { - mid = (*env)->GetMethodID(env, cls, "setAttribute", "(IZ)V"); - if (mid == 0) return JNI_FALSE; - (*env)->CallVoidMethod(env, fileInfo, mid, ATTRIBUTE_READ_ONLY, JNI_TRUE); - } - -#if USE_ARCHIVE_FLAG - // archive? - if ((info.st_flags & SF_ARCHIVED) == SF_ARCHIVED) { - mid = (*env)->GetMethodID(env, cls, "setAttribute", "(IZ)V"); - if (mid == 0) return JNI_FALSE; - (*env)->CallVoidMethod(env, fileInfo, mid, ATTRIBUTE_ARCHIVE, JNI_TRUE); - } -#endif - - // executable? - if ((info.st_mode & S_IXUSR) == S_IXUSR) { - mid = (*env)->GetMethodID(env, cls, "setAttribute", "(IZ)V"); - if (mid == 0) return JNI_FALSE; - (*env)->CallVoidMethod(env, fileInfo, mid, ATTRIBUTE_EXECUTABLE, JNI_TRUE); - } - return JNI_TRUE; -} - -#if defined(EFS_SYMLINK_SUPPORT) -/* - * Set symbolic link information in IFileInfo - */ -jboolean setSymlinkInFileInfo (JNIEnv *env, jobject fileInfo, jstring linkTarget) { - jclass cls; - jmethodID mid; - - cls = (*env)->GetObjectClass(env, fileInfo); - if (cls == 0) return JNI_FALSE; - - // set symlink attribute - mid = (*env)->GetMethodID(env, cls, "setAttribute", "(IZ)V"); - if (mid == 0) return JNI_FALSE; - (*env)->CallVoidMethod(env, fileInfo, mid, ATTRIBUTE_SYMLINK, JNI_TRUE); - - // set link target - mid = (*env)->GetMethodID(env, cls, "setStringAttribute", "(ILjava/lang/String;)V"); - if (mid == 0) return JNI_FALSE; - (*env)->CallVoidMethod(env, fileInfo, mid, ATTRIBUTE_LINK_TARGET, linkTarget); - - return JNI_TRUE; -} -#endif - -/* - * Class: org_eclipse_core_internal_filesystem_local_LocalFileNatives - * Method: internalGetFileInfo - * Signature: ([CLorg/eclipse/core/filesystem/IFileInfo;)Z - */ -JNIEXPORT jboolean JNICALL Java_org_eclipse_core_internal_filesystem_local_LocalFileNatives_internalGetFileInfo - (JNIEnv *env, jclass clazz, jbyteArray target, jobject fileInfo) { - // shouldn't ever be called - there is only a Unicode-specific call on MacOS X - return JNI_FALSE; -} - -/* - * Class: org_eclipse_core_internal_filesystem_local_LocalFileNatives - * Method: internalGetFileInfoW - * Signature: ([CLorg/eclipse/core/filesystem/IFileInfo;)Z - */ -JNIEXPORT jboolean JNICALL Java_org_eclipse_core_internal_filesystem_local_LocalFileNatives_internalGetFileInfoW - (JNIEnv *env, jclass clazz, jcharArray target, jobject fileInfo) { - - struct stat info; - jint code; - jstring linkTarget = NULL; - - /* get stat */ - char *name= (char*) getUTF8ByteArray(env, target); -#if defined(EFS_SYMLINK_SUPPORT) - //do an lstat first to see if it is a symbolic link - code = lstat(name, &info); - if (code == 0 && (S_ISLNK(info.st_mode))) { - //symbolic link: read link target - char buf[PATH_MAX+1]; - int len; - len = readlink((const char*)name, buf, PATH_MAX); - if (len>0) { - buf[len]=0; - } else { - buf[0]=0; - } - // Mac OS encodes symlink target using UTF-8, ignoring platform default - linkTarget = (*env)->NewStringUTF(env, buf); - setSymlinkInFileInfo(env, fileInfo, linkTarget); - - //stat link target (will fail for broken links) - code = stat((const char*)name, &info); - } -#else - code = stat(name, &info); -#endif - free(name); - - /* test if an error occurred */ - if (code == -1) - return JNI_FALSE; - return convertStatToFileInfo(env, info, fileInfo); -} - -/* - * Class: org_eclipse_core_internal_filesystem_local_LocalFileNatives - * Method: internalCopyAttributes - * Signature: ([B[BZ)Z - */ -JNIEXPORT jboolean JNICALL Java_org_eclipse_core_internal_filesystem_local_LocalFileNatives_internalCopyAttributes - (JNIEnv *env, jclass clazz, jbyteArray source, jbyteArray destination, jboolean copyLastModified) { - // shouldn't ever be called - there is only a Unicode-specific call on MacOS X - return JNI_FALSE; -} - -/* - * Class: org_eclipse_core_internal_filesystem_local_LocalFileNatives - * Method: internalCopyAttributesW - * Signature: ([C[CZ)Z - */ -JNIEXPORT jboolean JNICALL Java_org_eclipse_core_internal_filesystem_local_LocalFileNatives_internalCopyAttributesW - (JNIEnv *env, jclass clazz, jcharArray source, jcharArray destination, jboolean copyLastModified) { - - struct stat info; - struct utimbuf ut; - int code; - char *sourceFile= (char*) getUTF8ByteArray(env, source); - char *destinationFile= (char*) getUTF8ByteArray(env, destination); - - code= stat(sourceFile, &info); - if (code != 0) goto fail; - code= chmod(destinationFile, info.st_mode); - if (code != 0) goto fail; - - chflags(destinationFile, info.st_flags); // ignore return code - if (copyLastModified) { - ut.actime= info.st_atime; - ut.modtime= info.st_mtime; - code= utime(destinationFile, &ut); - } - -fail: - free(sourceFile); - free(destinationFile); - return code == 0; -} - -/* - * Class: org_eclipse_core_internal_filesystem_local_LocalFileNatives - * Method: internalSetFileInfo - * Signature: ([BLorg/eclipse/core/filesystem/IFileInfo;)Z - */ -JNIEXPORT jboolean JNICALL Java_org_eclipse_core_internal_filesystem_local_LocalFileNatives_internalSetFileInfo - (JNIEnv *env, jclass clazz, jcharArray target, jobject obj) { - // shouldn't ever be called - there is only a Unicode-specific call on MacOS X - return JNI_FALSE; - -} - -mode_t getumask() { - // in case something goes wrong just return 63 which is 0077 in octals - mode_t mask = 63; - - int fds[2]; - if (pipe(fds) == -1) { - return mask; - } - - pid_t child_pid; - child_pid = fork(); - - if (child_pid == 0) { - // child process - ssize_t bytes_written = 0; - close(fds[0]); - mask = umask(0); - while (1) { - ssize_t written = write(fds[1], &mask + bytes_written, sizeof(mask) - bytes_written); - if (written == -1) { - if (errno != EINTR) { - break; - } - } else { - bytes_written += written; - if (bytes_written == sizeof(mask)) { - break; - } - } - } - close(fds[1]); - _exit(0); - } else if (child_pid != -1) { - // parent process, fork succeded - int stat_loc; - ssize_t bytes_read = 0; - mode_t buf; - close(fds[1]); - while (1) { - ssize_t b_read = read(fds[0], &buf + bytes_read, sizeof(buf) - bytes_read); - if (b_read == -1) { - if (errno != EINTR) { - break; - } - } else { - if (b_read == 0) { - break; - } - bytes_read += b_read; - if (bytes_read == sizeof(mask)) { - break; - } - } - } - if (bytes_read == sizeof(mask)) { - mask = buf; - } - close(fds[0]); - waitpid(child_pid, &stat_loc, 0); - } else { - // parent process, fork failed - close(fds[0]); - close(fds[1]); - } - - return mask; -} - -/* - * Class: org_eclipse_core_internal_filesystem_local_LocalFileNatives - * Method: internalSetFileInfoW - * Signature: ([BLorg/eclipse/core/filesystem/IFileInfo;)Z - */ -JNIEXPORT jboolean JNICALL Java_org_eclipse_core_internal_filesystem_local_LocalFileNatives_internalSetFileInfoW - (JNIEnv *env, jclass clazz, jcharArray target, jobject obj, jint options) { - jint code = -1; - jmethodID mid; - jboolean executable, readOnly, archive; - jclass cls; - - /* find out if we need to set the readonly bit */ - cls = (*env)->GetObjectClass(env, obj); - mid = (*env)->GetMethodID(env, cls, "getAttribute", "(I)Z"); - if (mid == 0) goto fail; - readOnly = (*env)->CallBooleanMethod(env, obj, mid, ATTRIBUTE_READ_ONLY); - - /* find out if we need to set the executable bit */ - executable = (*env)->CallBooleanMethod(env, obj, mid, ATTRIBUTE_EXECUTABLE); - - /* find out if we need to set the archive bit */ - archive = (*env)->CallBooleanMethod(env, obj, mid, ATTRIBUTE_ARCHIVE); - - /* get the current permissions */ - jbyte *name = getUTF8ByteArray(env, target); - struct stat info; - int result= stat((char*)name, &info); - if (result != 0) goto fail; - - /* create the mask for the relevant bits */ - mode_t mask = info.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO); - mode_t oldmask = mask; - int flags = info.st_flags; - -#if USE_ARCHIVE_FLAG - if (archive) - flags |= SF_ARCHIVED; // set archive bit - else - flags &= ~SF_ARCHIVED; // clear archive bit -#endif - - if (executable) - mask |= S_IXUSR | ((S_IXGRP | S_IXOTH) & ~process_umask); - else - mask &= ~(S_IXUSR | S_IXGRP | S_IXOTH); // clear all 'x' - - if (readOnly) { - mask &= ~(S_IWUSR | S_IWGRP | S_IWOTH); // clear all 'w' -#if USE_IMMUTABLE_FLAG - flags |= UF_IMMUTABLE; // set immutable flag for usr -#endif - } else { - mask |= S_IRUSR | S_IWUSR | ((S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH) & ~process_umask); -#if USE_IMMUTABLE_FLAG - flags &= ~UF_IMMUTABLE; // try to clear immutable flags for usr -#endif - } - - /* call chmod & chflags syscalls in correct order */ - if (readOnly) { - if (mask != oldmask) - result |= chmod((char*)name, mask); - if (flags != info.st_flags) - result |= chflags((char*)name, flags); - } else { - if (flags != info.st_flags) - result |= chflags((char*)name, flags); - if (mask != oldmask) - result |= chmod((char*)name, mask); - } - -fail: - free(name); - return result == 0; -} - -JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) { - process_umask = getumask(); - return JNI_VERSION_1_1; -} Index: natives/unix/README.TXT =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.core.filesystem/natives/unix/README.TXT,v retrieving revision 1.2 diff -u -r1.2 README.TXT --- natives/unix/README.TXT 27 Apr 2007 15:58:07 -0000 1.2 +++ natives/unix/README.TXT 20 Jan 2010 13:15:17 -0000 @@ -1,3 +1,3 @@ This directory contains the source code for Unix-based platforms, -including Linux, HPUX, and Solaris. These platforms all share the same -C source, but have different makefiles and includes \ No newline at end of file +including AIX, HPUX, Linux, Mac OS X, and Solaris. These platforms +all share the same C source, but have different makefiles. \ No newline at end of file Index: natives/unix/localfile.c =================================================================== RCS file: natives/unix/localfile.c diff -N natives/unix/localfile.c --- natives/unix/localfile.c 16 Dec 2009 11:59:59 -0000 1.13 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,404 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2000, 2009 IBM Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * IBM Corporation - initial API and implementation - * Red Hat Incorporated - get/setResourceAttribute code - * Martin Oberhuber (Wind River) - [170317] add symbolic link support to API - * Corey Ashford (IBM) - [177400] fix threading issues on Linux-PPC - * Martin Oberhuber (Wind River) - [183137] liblocalfile for solaris-sparc - * Martin Oberhuber (Wind River) - [184534] get attributes from native lib - *******************************************************************************/ -#include -#include -#include -#include -#include -#include -#include -#include -#include "../localfile.h" -#include - -mode_t process_umask; - -/* - * 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) { - jsize n; - jbyte *temp, *result; - - temp = (*env)->GetByteArrayElements(env, target, 0); - n = (*env)->GetArrayLength(env, target); - result = malloc((n+1) * sizeof(jbyte)); - memcpy(result, temp, n * sizeof(jbyte)); - result[n] = '\0'; - (*env)->ReleaseByteArrayElements(env, target, temp, 0); - return result; -} - -#if defined(EFS_SYMLINK_SUPPORT) -/* - * Get a Java String from a java byte array, using the default charset. - * Uses Convert.fromPlatformBytes([B). - */ -jstring getString(JNIEnv *env, jbyteArray source) { - static jclass clsConvert = 0; - jmethodID midFromPlatformBytes = 0; - if (clsConvert == 0) { - clsConvert = (*env)->FindClass(env, "org/eclipse/core/internal/filesystem/local/Convert"); - if (clsConvert == 0) return NULL; - // Ensure class isn't garbage collected between calls to this function. - clsConvert = (*env)->NewGlobalRef(env, clsConvert); - } - midFromPlatformBytes = (*env)->GetStaticMethodID(env, clsConvert, "fromPlatformBytes", "([B)Ljava/lang/String;"); - if (midFromPlatformBytes == 0) return NULL; - return (*env)->CallStaticObjectMethod(env, clsConvert, midFromPlatformBytes, source); -} -#endif - -/* - * Class: org_eclipse_core_internal_filesystem_local_LocalFileNatives - * Method: nativeAttributes - * Signature: ()I - */ -JNIEXPORT jint JNICALL Java_org_eclipse_core_internal_filesystem_local_LocalFileNatives_nativeAttributes - (JNIEnv *env, jclass clazz) { -#if defined(EFS_SYMLINK_SUPPORT) - return ATTRIBUTE_READ_ONLY | ATTRIBUTE_EXECUTABLE | ATTRIBUTE_SYMLINK | ATTRIBUTE_LINK_TARGET; -#else - return ATTRIBUTE_READ_ONLY | ATTRIBUTE_EXECUTABLE; -#endif -} - - -/* - * Class: org_eclipse_core_internal_filesystem_local_LocalFileNatives - * Method: internalIsUnicode - * Signature: ()Z - */ -JNIEXPORT jboolean JNICALL Java_org_eclipse_core_internal_filesystem_local_LocalFileNatives_internalIsUnicode - (JNIEnv *env, jclass clazz) { - // no specific support for Unicode-based file names on *nix - return JNI_FALSE; -} - -/* - * Converts a stat structure to IFileInfo - */ -jboolean convertStatToFileInfo (JNIEnv *env, struct stat info, jobject fileInfo) { - jclass cls; - jmethodID mid; - - cls = (*env)->GetObjectClass(env, fileInfo); - if (cls == 0) return JNI_FALSE; - - // select interesting information - //exists - mid = (*env)->GetMethodID(env, cls, "setExists", "(Z)V"); - if (mid == 0) return JNI_FALSE; - (*env)->CallVoidMethod(env, fileInfo, mid, JNI_TRUE); - - // last modified - mid = (*env)->GetMethodID(env, cls, "setLastModified", "(J)V"); - if (mid == 0) return JNI_FALSE; - (*env)->CallVoidMethod(env, fileInfo, mid, ((jlong) info.st_mtime) * 1000); /* lower bits */ - - // file length - mid = (*env)->GetMethodID(env, cls, "setLength", "(J)V"); - if (mid == 0) return JNI_FALSE; - (*env)->CallVoidMethod(env, fileInfo, mid, (jlong)info.st_size); - - // folder or file? - if (S_ISDIR(info.st_mode)) { - mid = (*env)->GetMethodID(env, cls, "setAttribute", "(IZ)V"); - if (mid == 0) return JNI_FALSE; - (*env)->CallVoidMethod(env, fileInfo, mid, ATTRIBUTE_DIRECTORY, JNI_TRUE); - } - - // read-only? - if ((info.st_mode & S_IWRITE) != S_IWRITE) { - mid = (*env)->GetMethodID(env, cls, "setAttribute", "(IZ)V"); - if (mid == 0) return JNI_FALSE; - (*env)->CallVoidMethod(env, fileInfo, mid, ATTRIBUTE_READ_ONLY, JNI_TRUE); - } - - // executable? - if ((info.st_mode & S_IXUSR) == S_IXUSR) { - mid = (*env)->GetMethodID(env, cls, "setAttribute", "(IZ)V"); - if (mid == 0) return JNI_FALSE; - (*env)->CallVoidMethod(env, fileInfo, mid, ATTRIBUTE_EXECUTABLE, JNI_TRUE); - } - - return JNI_TRUE; -} - -#if defined(EFS_SYMLINK_SUPPORT) -/* - * Set symbolic link information in IFileInfo - */ -jboolean setSymlinkInFileInfo (JNIEnv *env, jobject fileInfo, jstring linkTarget) { - jclass cls; - jmethodID mid; - - cls = (*env)->GetObjectClass(env, fileInfo); - if (cls == 0) return JNI_FALSE; - - // set symlink attribute - mid = (*env)->GetMethodID(env, cls, "setAttribute", "(IZ)V"); - if (mid == 0) return JNI_FALSE; - (*env)->CallVoidMethod(env, fileInfo, mid, ATTRIBUTE_SYMLINK, JNI_TRUE); - - // set link target - mid = (*env)->GetMethodID(env, cls, "setStringAttribute", "(ILjava/lang/String;)V"); - if (mid == 0) return JNI_FALSE; - (*env)->CallVoidMethod(env, fileInfo, mid, ATTRIBUTE_LINK_TARGET, linkTarget); -} -#endif - -/* - * Class: org_eclipse_core_internal_filesystem_local_LocalFileNatives - * Method: internalGetFileInfo - * Signature: ([CLorg/eclipse/core/filesystem/IFileInfo;)Z - */ -JNIEXPORT jboolean JNICALL Java_org_eclipse_core_internal_filesystem_local_LocalFileNatives_internalGetFileInfo - (JNIEnv *env, jclass clazz, jbyteArray target, jobject fileInfo) { - struct stat info; - jlong result; - jint code; - jbyte *name; - jstring linkTarget = NULL; - - /* get stat */ - name = getByteArray(env, target); -#if defined(EFS_SYMLINK_SUPPORT) - //do an lstat first to see if it is a symbolic link - code = lstat((const char*)name, &info); - if (code == 0 && S_ISLNK(info.st_mode)) { - //symbolic link: read link target - char buf[PATH_MAX+1]; - int len; - jbyteArray barr; - len = readlink((const char*)name, buf, PATH_MAX); - if (len>0) { - barr = (*env)->NewByteArray(env, len); - (*env)->SetByteArrayRegion(env, barr, 0, len, buf); - } else { - barr = (*env)->NewByteArray(env, 0); - } - linkTarget = getString(env, barr); - setSymlinkInFileInfo(env, fileInfo, linkTarget); - - //stat link target (will fail for broken links) - code = stat((const char*)name, &info); - } -#else - code = stat((const char*)name, &info); -#endif - free(name); - - /* test if an error occurred */ - if (code == -1) - return 0; - return convertStatToFileInfo(env, info, fileInfo); -} - -/* - * Class: org_eclipse_core_internal_filesystem_local_LocalFileNatives - * Method: internalGetFileInfoW - * Signature: ([CLorg/eclipse/core/filesystem/IFileInfo;)Z - */ -JNIEXPORT jboolean JNICALL Java_org_eclipse_core_internal_filesystem_local_LocalFileNatives_internalGetFileInfoW - (JNIEnv *env, jclass clazz, jcharArray target, jobject fileInfo) { - // shouldn't ever be called - there is no Unicode-specific calls on *nix - return JNI_FALSE; -} - -/* - * Class: org_eclipse_core_internal_filesystem_local_LocalFileNatives - * Method: internalCopyAttributes - * Signature: ([B[BZ)Z - */ -JNIEXPORT jboolean JNICALL Java_org_eclipse_core_internal_filesystem_local_LocalFileNatives_internalCopyAttributes - (JNIEnv *env, jclass clazz, jbyteArray source, jbyteArray destination, jboolean copyLastModified) { - - struct stat info; - struct utimbuf ut; - jbyte *sourceFile, *destinationFile; - jint code; - - sourceFile = getByteArray(env, source); - destinationFile = getByteArray(env, destination); - - code = stat((const char*)sourceFile, &info); - if (code == 0) { - code = chmod((const char*)destinationFile, info.st_mode); - if (code == 0 && copyLastModified) { - ut.actime = info.st_atime; - ut.modtime = info.st_mtime; - code = utime((const char*)destinationFile, &ut); - } - } - - free(sourceFile); - free(destinationFile); - return code != -1; -} - -/* - * Class: org_eclipse_core_internal_filesystem_local_LocalFileNatives - * Method: internalCopyAttributesW - * Signature: ([C[CZ)Z - */ -JNIEXPORT jboolean JNICALL Java_org_eclipse_core_internal_filesystem_local_LocalFileNatives_internalCopyAttributesW - (JNIEnv *env, jclass clazz, jcharArray source, jcharArray destination, jboolean copyLastModified) { - // shouldn't ever be called - there is no Unicode-specific calls on *nix - return JNI_FALSE; -} - -mode_t getumask() { - // in case something goes wrong just return 63 which is 0077 in octals - mode_t mask = 63; - - int fds[2]; - if (pipe(fds) == -1) { - return mask; - } - - pid_t child_pid; - child_pid = fork(); - - if (child_pid == 0) { - // child process - ssize_t bytes_written = 0; - close(fds[0]); - mask = umask(0); - while (1) { - ssize_t written = write(fds[1], &mask + bytes_written, sizeof(mask) - bytes_written); - if (written == -1) { - if (errno != EINTR) { - break; - } - } else { - bytes_written += written; - if (bytes_written == sizeof(mask)) { - break; - } - } - } - close(fds[1]); - _exit(0); - } else if (child_pid != -1) { - // parent process, fork succeded - int stat_loc; - ssize_t bytes_read = 0; - mode_t buf; - close(fds[1]); - while (1) { - ssize_t b_read = read(fds[0], &buf + bytes_read, sizeof(buf) - bytes_read); - if (b_read == -1) { - if (errno != EINTR) { - break; - } - } else { - if (b_read == 0) { - break; - } - bytes_read += b_read; - if (bytes_read == sizeof(mask)) { - break; - } - } - } - if (bytes_read == sizeof(mask)) { - mask = buf; - } - close(fds[0]); - waitpid(child_pid, &stat_loc, 0); - } else { - // parent process, fork failed - close(fds[0]); - close(fds[1]); - } - - return mask; -} - -/* - * Class: org_eclipse_core_internal_filesystem_local_LocalFileNatives - * Method: internalSetFileInfo - * Signature: ([BLorg/eclipse/core/filesystem/IFileInfo;)Z - */ -JNIEXPORT jboolean JNICALL Java_org_eclipse_core_internal_filesystem_local_LocalFileNatives_internalSetFileInfo - (JNIEnv *env, jclass clazz, jcharArray target, jobject obj) { - - mode_t mask; - struct stat info; - jbyte *name; - jint code = -1; - jmethodID mid; - jboolean executable, readOnly; - jclass cls; - - /* find out if we need to set the readonly bit */ - cls = (*env)->GetObjectClass(env, obj); - mid = (*env)->GetMethodID(env, cls, "getAttribute", "(I)Z"); - if (mid == 0) goto fail; - readOnly = (*env)->CallBooleanMethod(env, obj, mid, ATTRIBUTE_READ_ONLY); - - /* find out if we need to set the executable bit */ - executable = (*env)->CallBooleanMethod(env, obj, mid, ATTRIBUTE_EXECUTABLE); - - /* get the current permissions */ - name = getByteArray(env, target); - code = stat((const char*)name, &info); - - /* create the mask */ - mask = S_IRUSR | - S_IWUSR | - S_IXUSR | - S_IRGRP | - S_IWGRP | - S_IXGRP | - S_IROTH | - S_IWOTH | - S_IXOTH; - mask &= info.st_mode; - if (executable) - mask |= S_IXUSR | ((S_IXGRP | S_IXOTH) & ~process_umask); - else - mask &= ~(S_IXUSR | S_IXGRP | S_IXOTH); - if (readOnly) - mask &= ~(S_IWUSR | S_IWGRP | S_IWOTH); - else - mask |= S_IRUSR | S_IWUSR | ((S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH) & ~process_umask); - /* write the permissions */ - code = chmod((const char*)name, mask); - -fail: - if (name) free(name); - return code != -1; -} - -/* - * Class: org_eclipse_core_internal_filesystem_local_LocalFileNatives - * Method: internalSetFileInfoW - * Signature: ([BLorg/eclipse/core/filesystem/IFileInfo;)Z - */ -JNIEXPORT jboolean JNICALL Java_org_eclipse_core_internal_filesystem_local_LocalFileNatives_internalSetFileInfoW - (JNIEnv *env, jclass clazz, jcharArray target, jobject obj, jint options) { - // shouldn't ever be called - there is no Unicode-specific calls on *nix - return JNI_FALSE; -} - -JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) { - process_umask = getumask(); - return JNI_VERSION_1_1; -} Index: natives/unix/linux/Makefile =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.core.filesystem/natives/unix/linux/Makefile,v retrieving revision 1.4 diff -u -r1.4 Makefile --- natives/unix/linux/Makefile 19 Nov 2009 15:43:05 -0000 1.4 +++ natives/unix/linux/Makefile 20 Jan 2010 13:15:17 -0000 @@ -1,32 +1,37 @@ -#********************************************************************** -# Copyright (c) 2000, 2009 IBM Corporation and others. -# All rights reserved. This program and the accompanying materials +#****************************************************************************** +# Copyright (c) 2010 IBM Corporation and others. +# All rights reserved. This program and the accompanying materials # are made available under the terms of the Eclipse Public License v1.0 # which accompanies this distribution, and is available at # http://www.eclipse.org/legal/epl-v10.html -#********************************************************************** # -# makefile for libcore.so +# Contributors: +# IBM Corporation - initial API and implementation +#******************************************************************************/ +# +# makefile for libunixfile_1_0_0.so -CORE.C = ../localfile.c -CORE.O = localfile.o -LIB_NAME = liblocalfile.so -LIB_NAME_FULL = liblocalfile_1_0_0.so +CORE.C = ../unixfile.c +CORE.O = unixfile.o +LIB_NAME = libunixfile.so +LIB_NAME_FULL = libunixfile_1_0_0.so #Set this to be your OS type OS_TYPE = linux #Set this to be the location of your JRE -JAVA_HOME = ~/vm/sun142 +JAVA_HOME = /usr/lib/jvm/java-1.5.0-ibm-1.5.0.9/ JDK_INCLUDE = -I ${JAVA_HOME}/include -I ${JAVA_HOME}/include/${OS_TYPE} -COMMON_INCLUDE = -I include -#OPT_FLAGS=-g OPT_FLAGS=-O -s -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -core : - gcc $(OPT_FLAGS) -fPIC -c $(JDK_INCLUDE) $(COMMON_INCLUDE) -o $(CORE.O) $(CORE.C) +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 : +clean: rm -f $(CORE.O) $(LIB_NAME_FULL) + +install: core + rm -f ../../../../org.eclipse.core.filesystem.linux.x86/os/linux/x86/libunixfile_1_0_0.so + mv libunixfile_1_0_0.so ../../../../org.eclipse.core.filesystem.linux.x86/os/linux/x86/ Index: natives/unix/linux/include/os_custom.h =================================================================== RCS file: natives/unix/linux/include/os_custom.h diff -N natives/unix/linux/include/os_custom.h --- natives/unix/linux/include/os_custom.h 23 Apr 2007 16:32:09 -0000 1.2 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,23 +0,0 @@ -/*********************************************************************** -* Copyright (c) 2005, 2007 IBM Corporation and others. -* All rights reserved. This program and the accompanying materials -* are made available under the terms of the Eclipse Public License v1.0 -* which accompanies this distribution, and is available at -* http://www.eclipse.org/legal/epl-v10.html -* -* Contributors: -* IBM Corporation - initial API and implementation -* Martin Oberhuber (Wind River) - [183137] liblocalfile for solaris-sparc -***********************************************************************/ - -/* Use this directive when introducing platform-specific code in localfile.c */ -#ifndef LINUX -#define LINUX -#endif - -/* Linux supports reading symbolic links */ -#ifndef EFS_SYMLINK_SUPPORT -#define EFS_SYMLINK_SUPPORT -#endif -#include -#include Index: natives/unix/macosx/Makefile =================================================================== RCS file: natives/unix/macosx/Makefile diff -N natives/unix/macosx/Makefile --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ natives/unix/macosx/Makefile 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,30 @@ +#****************************************************************************** +# Copyright (c) 2010 IBM Corporation and others. +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# IBM Corporation - initial API and implementation +#******************************************************************************/ +# +# makefile for libunixfile_1_0_0.jnilib + +CORE.C=../unixfile.c +LIB_NAME_FULL=libunixfile_1_0_0.jnilib + +JDK_INCLUDE=-I /System/Library/Frameworks/JavaVM.framework/Headers +FRAMEWORKS=-framework JavaVM -framework CoreServices +# define MACOSX to include Mac OS X specific code +CC_FLAGS=-arch i386 -arch ppc -arch x86_64 -mmacosx-version-min=10.4 -DMACOSX + +core: + cc $(JDK_INCLUDE) $(CORE.C) -o $(LIB_NAME_FULL) -bundle $(FRAMEWORKS) $(CC_FLAGS) + +clean: + rm -f $(LIB_NAME_FULL) + +install: + rm -f ../../../../org.eclipse.core.filesystem.macosx/os/macosx/$(LIB_NAME_FULL) + mv $(LIB_NAME_FULL) ../../../../org.eclipse.core.filesystem.macosx/os/macosx/ Index: natives/unix/unixfile.c =================================================================== RCS file: natives/unix/unixfile.c diff -N natives/unix/unixfile.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ natives/unix/unixfile.c 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,292 @@ +/******************************************************************************* + * Copyright (c) 2010 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined MACOSX +#include +#endif + +#include "unixfile.h" + +/* + * 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) +{ + jsize len; + jbyte *temp, *result; + + temp = (*env)->GetByteArrayElements(env, target, 0); + len = (*env)->GetArrayLength(env, target); + result = malloc((len + 1) * sizeof(jbyte)); + memcpy(result, temp, len * sizeof(jbyte)); + result[len] = '\0'; + (*env)->ReleaseByteArrayElements(env, target, temp, 0); + return result; +} + +/* + * Fills StructStat object with data from struct stat. + */ +jint convertStatToObject(JNIEnv *env, struct stat info, jobject stat_object) +{ + jclass cls; + jfieldID fid; + jboolean readOnly; + + cls = (*env)->GetObjectClass(env, stat_object); + if (cls == 0) return -1; + + fid = (*env)->GetFieldID(env, cls, "st_mode", "I"); + if (fid == 0) return -1; + (*env)->SetIntField(env, stat_object, fid, info.st_mode); + + fid = (*env)->GetFieldID(env, cls, "st_size", "J"); + if (fid == 0) return -1; + (*env)->SetLongField(env, stat_object, fid, info.st_size); + + fid = (*env)->GetFieldID(env, cls, "st_mtime", "J"); + if (fid == 0) return -1; + (*env)->SetLongField(env, stat_object, fid, info.st_mtime); + +#ifdef MACOSX + fid = (*env)->GetFieldID(env, cls, "st_flags", "J"); + if (fid == 0) return -1; + (*env)->SetLongField(env, stat_object, fid, info.st_flags); +#endif + + return 0; +} + +/* + * Class: org_eclipse_core_internal_filesystem_local_unix_UnixFileNatives + * Method: chmod + * Signature: ([BI)I + */ +JNIEXPORT jint JNICALL Java_org_eclipse_core_internal_filesystem_local_unix_UnixFileNatives_chmod + (JNIEnv *env, jclass clazz, jbyteArray path, jint mode) +{ + int code; + char *name; + + name = (char*) getByteArray(env, path); + code = chmod(name, mode); + free(name); + return code; +} + +/* + * Class: org_eclipse_core_internal_filesystem_local_unix_UnixFileNatives + * Method: chflags + * Signature: ([BI)I + */ +JNIEXPORT jint JNICALL Java_org_eclipse_core_internal_filesystem_local_unix_UnixFileNatives_chflags + (JNIEnv *env, jclass clazz, jbyteArray path, jint flags) +{ +#ifdef MACOSX + int code; + char *name; + + name = (char*) getByteArray(env, path); + code = chflags(name, flags); + free(name); + return code; +#else + return -1; +#endif +} + +/* + * Class: org_eclipse_core_internal_filesystem_local_unix_UnixFileNatives + * Method: stat + * Signature: ([BLorg/eclipse/core/internal/filesystem/local/unix/StructStat;)I + */ +JNIEXPORT jint JNICALL Java_org_eclipse_core_internal_filesystem_local_unix_UnixFileNatives_stat + (JNIEnv *env, jclass clazz, jbyteArray path, jobject buf) +{ + jint code; + char *name; + struct stat info; + + name = (char*) getByteArray(env, path); + code = stat(name, &info); + free(name); + if (code != -1) + return convertStatToObject(env, info, buf); + else + return code; +} + +/* + * Class: org_eclipse_core_internal_filesystem_local_unix_UnixFileNatives + * Method: lstat + * Signature: ([BLorg/eclipse/core/internal/filesystem/local/unix/StructStat;)I + */ +JNIEXPORT jint JNICALL Java_org_eclipse_core_internal_filesystem_local_unix_UnixFileNatives_lstat + (JNIEnv *env, jclass clazz, jbyteArray path, jobject buf) +{ + jint code; + char *name; + struct stat info; + + name = (char*) getByteArray(env, path); + code = lstat(name, &info); + free(name); + if (code != -1) + return convertStatToObject(env, info, buf); + else + return code; +} + +/* + * Class: org_eclipse_core_internal_filesystem_local_unix_UnixFileNatives + * Method: readlink + * Signature: ([B[BJ)J + */ +JNIEXPORT jlong JNICALL Java_org_eclipse_core_internal_filesystem_local_unix_UnixFileNatives_readlink + (JNIEnv *env, jclass clazz, jbyteArray path, jbyteArray buf, jlong bufsiz) { + jint code; + char *name; + ssize_t len; + char temp[PATH_MAX+1]; + jstring linkTarget = NULL; + + name = getByteArray(env, path); + len = readlink((const char*)name, temp, PATH_MAX); + free(name); + if (len > 0) { + temp[len] = 0; + (*env)->SetByteArrayRegion(env, buf, 0, len, temp); + } + else { + temp[0] = 0; + (*env)->SetByteArrayRegion(env, buf, 0, 0, temp); + } + return len; +} + +/* + * Class: org_eclipse_core_internal_filesystem_local_unix_UnixFileNatives + * Method: errno + * Signature: ()I + */ +JNIEXPORT jint JNICALL Java_org_eclipse_core_internal_filesystem_local_unix_UnixFileNatives_errno + (JNIEnv *env, jclass clazz) +{ + return errno; +} + +/* + * Class: org_eclipse_core_internal_filesystem_local_unix_UnixFileNatives + * Method: libattr + * Signature: ()I + */ +JNIEXPORT jint JNICALL Java_org_eclipse_core_internal_filesystem_local_unix_UnixFileNatives_libattr + (JNIEnv *env, jclass clazz) +{ +#ifdef MACOSX + return UNICODE_SUPPORTED | CHFLAGS_SUPPORTED; +#else + return 0; +#endif +} + +/* + * Class: org_eclipse_core_internal_filesystem_local_unix_UnixFileNatives + * Method: tounicode + * Signature: ([C)[B + */ +JNIEXPORT jbyteArray JNICALL Java_org_eclipse_core_internal_filesystem_local_unix_UnixFileNatives_tounicode + (JNIEnv *env, jclass clazz, jcharArray buf) +{ +#ifdef MACOSX + jchar *temp; + jsize length; + CFStringRef str_ref; + CFIndex str_size; + jbyte *unicode_bytes; + jbyteArray ret; + + temp = (*env)->GetCharArrayElements(env, buf, 0); + length = (*env)->GetArrayLength(env, buf); + str_ref = CFStringCreateWithCharacters(kCFAllocatorDefault, temp, length); + str_size = CFStringGetMaximumSizeForEncoding(length, kCFStringEncodingUTF8) + 1; + unicode_bytes = (jbyte*) calloc(str_size, sizeof(jbyte)); + CFStringGetCString(str_ref, (char*) unicode_bytes, str_size, kCFStringEncodingUTF8); + ret = (*env)->NewByteArray(env, str_size); + if (ret == NULL) + return NULL; + (*env)->SetByteArrayRegion(env, ret, 0, str_size, unicode_bytes); + CFRelease(str_ref); + (*env)->ReleaseCharArrayElements(env, buf, temp, 0); + free(unicode_bytes); + return ret; +#else + return NULL; +#endif +} + +/* + * Class: org_eclipse_core_internal_filesystem_local_unix_UnixFileNatives + * Method: getflag + * Signature: ([B)I + */ +JNIEXPORT jint JNICALL Java_org_eclipse_core_internal_filesystem_local_unix_UnixFileNatives_getflag + (JNIEnv *env, jclass clazz, jbyteArray buf) +{ + char *flag; + jint ret = -1; + + flag = getByteArray(env, buf); + 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; +#ifdef MACOSX + else if (strcmp(flag, "UF_IMMUTABLE") == 0) + ret = UF_IMMUTABLE; + else if (strcmp(flag, "SF_IMMUTABLE") == 0) + ret = SF_IMMUTABLE; +#endif + free(flag); + return ret; +} Index: natives/unix/unixfile.h =================================================================== RCS file: natives/unix/unixfile.h diff -N natives/unix/unixfile.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ natives/unix/unixfile.h 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,114 @@ +/******************************************************************************* + * Copyright (c) 2010 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +#include + +#undef UNICODE_SUPPORTED +#define UNICODE_SUPPORTED 1L +#undef CHFLAGS_SUPPORTED +#define CHFLAGS_SUPPORTED 2L + +/* + * 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 StructStat object with data from struct stat. + */ +jint convertStatToObject(JNIEnv *, struct stat, jobject); + +/* DO NOT EDIT THIS FILE - it is machine generated */ + +/* Header for class org_eclipse_core_internal_filesystem_local_unix_UnixFileNatives */ + +#ifndef _Included_org_eclipse_core_internal_filesystem_local_unix_UnixFileNatives +#define _Included_org_eclipse_core_internal_filesystem_local_unix_UnixFileNatives +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Class: org_eclipse_core_internal_filesystem_local_unix_UnixFileNatives + * Method: chmod + * Signature: ([BI)I + */ +JNIEXPORT jint JNICALL Java_org_eclipse_core_internal_filesystem_local_unix_UnixFileNatives_chmod + (JNIEnv *, jclass, jbyteArray, jint); + +/* + * Class: org_eclipse_core_internal_filesystem_local_unix_UnixFileNatives + * Method: chflags + * Signature: ([BI)I + */ +JNIEXPORT jint JNICALL Java_org_eclipse_core_internal_filesystem_local_unix_UnixFileNatives_chflags + (JNIEnv *, jclass, jbyteArray, jint); + +/* + * Class: org_eclipse_core_internal_filesystem_local_unix_UnixFileNatives + * Method: stat + * Signature: ([BLorg/eclipse/core/internal/filesystem/local/unix/StructStat;)I + */ +JNIEXPORT jint JNICALL Java_org_eclipse_core_internal_filesystem_local_unix_UnixFileNatives_stat + (JNIEnv *, jclass, jbyteArray, jobject); + +/* + * Class: org_eclipse_core_internal_filesystem_local_unix_UnixFileNatives + * Method: lstat + * Signature: ([BLorg/eclipse/core/internal/filesystem/local/unix/StructStat;)I + */ +JNIEXPORT jint JNICALL Java_org_eclipse_core_internal_filesystem_local_unix_UnixFileNatives_lstat + (JNIEnv *, jclass, jbyteArray, jobject); + +/* + * Class: org_eclipse_core_internal_filesystem_local_unix_UnixFileNatives + * Method: readlink + * Signature: ([B[BJ)J + */ +JNIEXPORT jlong JNICALL Java_org_eclipse_core_internal_filesystem_local_unix_UnixFileNatives_readlink + (JNIEnv *, jclass, jbyteArray, jbyteArray, jlong); + +/* + * Class: org_eclipse_core_internal_filesystem_local_unix_UnixFileNatives + * Method: errno + * Signature: ()I + */ +JNIEXPORT jint JNICALL Java_org_eclipse_core_internal_filesystem_local_unix_UnixFileNatives_errno + (JNIEnv *, jclass); + +/* + * Class: org_eclipse_core_internal_filesystem_local_unix_UnixFileNatives + * Method: libattr + * Signature: ()I + */ +JNIEXPORT jint JNICALL Java_org_eclipse_core_internal_filesystem_local_unix_UnixFileNatives_libattr + (JNIEnv *, jclass); + +/* + * Class: org_eclipse_core_internal_filesystem_local_unix_UnixFileNatives + * Method: tounicode + * Signature: ([C)[B + */ +JNIEXPORT jbyteArray JNICALL Java_org_eclipse_core_internal_filesystem_local_unix_UnixFileNatives_tounicode + (JNIEnv *, jclass, jcharArray); + +/* + * Class: org_eclipse_core_internal_filesystem_local_unix_UnixFileNatives + * Method: getflag + * Signature: ([B)I + */ +JNIEXPORT jint JNICALL Java_org_eclipse_core_internal_filesystem_local_unix_UnixFileNatives_getflag + (JNIEnv *, jclass, jbyteArray); + +#ifdef __cplusplus +} +#endif +#endif Index: src/org/eclipse/core/filesystem/EFS.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.core.filesystem/src/org/eclipse/core/filesystem/EFS.java,v retrieving revision 1.16 diff -u -r1.16 EFS.java --- src/org/eclipse/core/filesystem/EFS.java 7 Apr 2008 08:55:40 -0000 1.16 +++ src/org/eclipse/core/filesystem/EFS.java 20 Jan 2010 13:15:35 -0000 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2008 IBM Corporation and others. + * Copyright (c) 2005, 2010 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -114,6 +114,126 @@ public static final int ATTRIBUTE_READ_ONLY = 1 << 1; /** + * Attribute constant (value 1 <<21) indicating that a + * file is marked with immutable flag. + * + * @see IFileStore#fetchInfo() + * @see IFileStore#putInfo(IFileInfo, int, IProgressMonitor) + * @see IFileInfo#getAttribute(int) + * @see IFileInfo#setAttribute(int, boolean) + * @since org.eclipse.core.filesystem 1.3 + */ + public static final int ATTRIBUTE_IMMUTABLE = 1 << 21; + + /** + * Attribute constant (value 1 <<22) indicating that a + * file's owner has a read permission. + * + * @see IFileStore#fetchInfo() + * @see IFileStore#putInfo(IFileInfo, int, IProgressMonitor) + * @see IFileInfo#getAttribute(int) + * @see IFileInfo#setAttribute(int, boolean) + * @since org.eclipse.core.filesystem 1.3 + */ + public static final int ATTRIBUTE_OWNER_READ = 1 << 22; + + /** + * Attribute constant (value 1 <<23) indicating that + * file's owner has a write permission. + * + * @see IFileStore#fetchInfo() + * @see IFileStore#putInfo(IFileInfo, int, IProgressMonitor) + * @see IFileInfo#getAttribute(int) + * @see IFileInfo#setAttribute(int, boolean) + * @since org.eclipse.core.filesystem 1.3 + */ + public static final int ATTRIBUTE_OWNER_WRITE = 1 << 23; + + /** + * Attribute constant (value 1 <<24) indicating that + * file's owner has an execute permission. + * + * @see IFileStore#fetchInfo() + * @see IFileStore#putInfo(IFileInfo, int, IProgressMonitor) + * @see IFileInfo#getAttribute(int) + * @see IFileInfo#setAttribute(int, boolean) + * @since org.eclipse.core.filesystem 1.3 + */ + public static final int ATTRIBUTE_OWNER_EXECUTE = 1 << 24; + + /** + * Attribute constant (value 1 <<25) indicating that + * users in file's group have a read permission. + * + * @see IFileStore#fetchInfo() + * @see IFileStore#putInfo(IFileInfo, int, IProgressMonitor) + * @see IFileInfo#getAttribute(int) + * @see IFileInfo#setAttribute(int, boolean) + * @since org.eclipse.core.filesystem 1.3 + */ + public static final int ATTRIBUTE_GROUP_READ = 1 << 25; + + /** + * Attribute constant (value 1 <<26) indicating that + * users in file's group have a write permission. + * + * @see IFileStore#fetchInfo() + * @see IFileStore#putInfo(IFileInfo, int, IProgressMonitor) + * @see IFileInfo#getAttribute(int) + * @see IFileInfo#setAttribute(int, boolean) + * @since org.eclipse.core.filesystem 1.3 + */ + public static final int ATTRIBUTE_GROUP_WRITE = 1 << 26; + + /** + * Attribute constant (value 1 <<27) indicating that + * users in file's group have an execute permission. + * + * @see IFileStore#fetchInfo() + * @see IFileStore#putInfo(IFileInfo, int, IProgressMonitor) + * @see IFileInfo#getAttribute(int) + * @see IFileInfo#setAttribute(int, boolean) + * @since org.eclipse.core.filesystem 1.3 + */ + public static final int ATTRIBUTE_GROUP_EXECUTE = 1 << 27; + + /** + * Attribute constant (value 1 <<28) indicating that + * other users have a read permission. + * + * @see IFileStore#fetchInfo() + * @see IFileStore#putInfo(IFileInfo, int, IProgressMonitor) + * @see IFileInfo#getAttribute(int) + * @see IFileInfo#setAttribute(int, boolean) + * @since org.eclipse.core.filesystem 1.3 + */ + public static final int ATTRIBUTE_OTHER_READ = 1 << 28; + + /** + * Attribute constant (value 1 <<29) indicating that + * other users have a write permission. + * + * @see IFileStore#fetchInfo() + * @see IFileStore#putInfo(IFileInfo, int, IProgressMonitor) + * @see IFileInfo#getAttribute(int) + * @see IFileInfo#setAttribute(int, boolean) + * @since org.eclipse.core.filesystem 1.3 + */ + public static final int ATTRIBUTE_OTHER_WRITE = 1 << 29; + + /** + * Attribute constant (value 1 <<30) indicating that + * other users have an execute permission. + * + * @see IFileStore#fetchInfo() + * @see IFileStore#putInfo(IFileInfo, int, IProgressMonitor) + * @see IFileInfo#getAttribute(int) + * @see IFileInfo#setAttribute(int, boolean) + * @since org.eclipse.core.filesystem 1.3 + */ + public static final int ATTRIBUTE_OTHER_EXECUTE = 1 << 30; + + /** * Attribute constant (value 1 <<2) indicating that a * file is a executable. * Index: src/org/eclipse/core/filesystem/provider/FileInfo.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.core.filesystem/src/org/eclipse/core/filesystem/provider/FileInfo.java,v retrieving revision 1.12 diff -u -r1.12 FileInfo.java --- src/org/eclipse/core/filesystem/provider/FileInfo.java 7 Apr 2008 08:55:39 -0000 1.12 +++ src/org/eclipse/core/filesystem/provider/FileInfo.java 20 Jan 2010 13:15:35 -0000 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2008 IBM Corporation and others. + * Copyright (c) 2005, 2010 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -13,6 +13,7 @@ import org.eclipse.core.filesystem.EFS; import org.eclipse.core.filesystem.IFileInfo; +import org.eclipse.core.internal.filesystem.local.LocalFileNativesManager; /** * This class should be used by file system providers in their implementation @@ -33,9 +34,9 @@ private static final int ATTRIBUTE_EXISTS = 1 << 16; /** - * Bit field of file attributes + * Bit field of file attributes. Initialized to specify a writable resource. */ - private int attributes = 0; + private int attributes = EFS.ATTRIBUTE_OWNER_WRITE | EFS.ATTRIBUTE_OWNER_READ; /** * The last modified time. @@ -113,7 +114,12 @@ } public boolean getAttribute(int attribute) { - return isSet(attribute); + if (attribute == EFS.ATTRIBUTE_READ_ONLY && isAttributeSuported(EFS.ATTRIBUTE_OWNER_WRITE)) + return (!isSet(EFS.ATTRIBUTE_OWNER_WRITE)) || isSet(EFS.ATTRIBUTE_IMMUTABLE); + else if (attribute == EFS.ATTRIBUTE_EXECUTABLE && isAttributeSuported(EFS.ATTRIBUTE_OWNER_EXECUTE)) + return isSet(EFS.ATTRIBUTE_OWNER_EXECUTE); + else + return isSet(attribute); } /* (non-Javadoc) @@ -165,10 +171,29 @@ * @see org.eclipse.core.filesystem.IFileInfo#setAttribute(int, boolean) */ public void setAttribute(int attribute, boolean value) { - if (value) - set(attribute); - else - clear(attribute); + if (attribute == EFS.ATTRIBUTE_READ_ONLY && isAttributeSuported(EFS.ATTRIBUTE_OWNER_WRITE)) { + if (value) { + clear(EFS.ATTRIBUTE_OWNER_WRITE | EFS.ATTRIBUTE_OTHER_WRITE | EFS.ATTRIBUTE_GROUP_WRITE); + set(EFS.ATTRIBUTE_IMMUTABLE); + } else { + set(EFS.ATTRIBUTE_OWNER_WRITE | EFS.ATTRIBUTE_OWNER_READ); + clear(EFS.ATTRIBUTE_IMMUTABLE); + } + } else if (attribute == EFS.ATTRIBUTE_EXECUTABLE && isAttributeSuported(EFS.ATTRIBUTE_OWNER_EXECUTE)) { + if (value) + set(EFS.ATTRIBUTE_OWNER_EXECUTE); + else + clear(EFS.ATTRIBUTE_OWNER_EXECUTE | EFS.ATTRIBUTE_GROUP_EXECUTE | EFS.ATTRIBUTE_OTHER_EXECUTE); + } else { + if (value) + set(attribute); + else + clear(attribute); + } + } + + private static boolean isAttributeSuported(int value) { + return (LocalFileNativesManager.getSupportedAttributes() & value) != 0; } /** Index: src/org/eclipse/core/internal/filesystem/Messages.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.core.filesystem/src/org/eclipse/core/internal/filesystem/Messages.java,v retrieving revision 1.7 diff -u -r1.7 Messages.java --- src/org/eclipse/core/internal/filesystem/Messages.java 3 Jun 2008 12:40:03 -0000 1.7 +++ src/org/eclipse/core/internal/filesystem/Messages.java 20 Jan 2010 13:15:35 -0000 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2007 IBM Corporation and others. + * Copyright (c) 2005, 2010 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -21,7 +21,7 @@ public static String copying; public static String couldnotDelete; public static String couldnotDeleteReadOnly; - public static String couldNotLoadLibrary; + public static String couldNotNativeLibrary; public static String couldNotMove; public static String couldNotRead; public static String couldNotWrite; Index: src/org/eclipse/core/internal/filesystem/local/Convert.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.core.filesystem/src/org/eclipse/core/internal/filesystem/local/Convert.java,v retrieving revision 1.6 diff -u -r1.6 Convert.java --- src/org/eclipse/core/internal/filesystem/local/Convert.java 29 Apr 2009 20:48:27 -0000 1.6 +++ src/org/eclipse/core/internal/filesystem/local/Convert.java 20 Jan 2010 13:15:35 -0000 @@ -72,20 +72,21 @@ /** * Calling new String(byte[] s) creates a new encoding object and other garbage. * This can be avoided by calling new String(byte[] s, String encoding) instead. - * @param source String in platform bytes + * @param source buffer with String in platform bytes + * @param length number of relevant bytes in the buffer * @return converted Java String * @since org.eclipse.core.filesystem 1.1 */ - public static String fromPlatformBytes(byte[] source) { + public static String fromPlatformBytes(byte[] source, int length) { if (defaultEncoding == null) - return new String(source); + return new String(source, 0, length); // try to use the default encoding try { - return new String(source, defaultEncoding); + return new String(source, 0, length, defaultEncoding); } catch (UnsupportedEncodingException e) { // null the default encoding so we don't try it again defaultEncoding = null; - return new String(source); + return new String(source, 0, length); } } Index: src/org/eclipse/core/internal/filesystem/local/LocalFile.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.core.filesystem/src/org/eclipse/core/internal/filesystem/local/LocalFile.java,v retrieving revision 1.32 diff -u -r1.32 LocalFile.java --- src/org/eclipse/core/internal/filesystem/local/LocalFile.java 10 Nov 2009 09:05:43 -0000 1.32 +++ src/org/eclipse/core/internal/filesystem/local/LocalFile.java 20 Jan 2010 13:15:35 -0000 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2009 IBM Corporation and others. + * Copyright (c) 2005, 2010 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -140,8 +140,8 @@ } public IFileInfo fetchInfo(int options, IProgressMonitor monitor) { - if (LocalFileNatives.usingNatives()) { - FileInfo info = LocalFileNatives.fetchFileInfo(filePath); + if (LocalFileNativesManager.isUsingNatives()) { + FileInfo info = LocalFileNativesManager.fetchFileInfo(filePath); //natives don't set the file name on all platforms if (info.getName().length() == 0) { String name = file.getName(); @@ -398,8 +398,8 @@ public void putInfo(IFileInfo info, int options, IProgressMonitor monitor) throws CoreException { boolean success = true; if ((options & EFS.SET_ATTRIBUTES) != 0) { - if (LocalFileNatives.usingNatives()) - success &= LocalFileNatives.setFileInfo(filePath, info, options); + if (LocalFileNativesManager.isUsingNatives()) + success &= LocalFileNativesManager.putFileInfo(filePath, info, options); } //native does not currently set last modified if ((options & EFS.SET_LAST_MODIFIED) != 0) Index: src/org/eclipse/core/internal/filesystem/local/LocalFileNatives.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.core.filesystem/src/org/eclipse/core/internal/filesystem/local/LocalFileNatives.java,v retrieving revision 1.12 diff -u -r1.12 LocalFileNatives.java --- src/org/eclipse/core/internal/filesystem/local/LocalFileNatives.java 27 Jun 2007 18:17:56 -0000 1.12 +++ src/org/eclipse/core/internal/filesystem/local/LocalFileNatives.java 20 Jan 2010 13:15:35 -0000 @@ -14,10 +14,6 @@ import org.eclipse.core.filesystem.IFileInfo; import org.eclipse.core.filesystem.IFileSystem; import org.eclipse.core.filesystem.provider.FileInfo; -import org.eclipse.core.internal.filesystem.Messages; -import org.eclipse.core.internal.filesystem.Policy; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.osgi.util.NLS; abstract class LocalFileNatives { private static boolean hasNatives = false; @@ -33,7 +29,7 @@ hasNatives = true; isUnicode = internalIsUnicode(); } catch (UnsatisfiedLinkError e) { - logMissingNativeLibrary(e); + // Nothing to do } } @@ -143,18 +139,12 @@ * be called if isUnicode is false). */ private static final native boolean internalSetFileInfoW(char[] fileName, IFileInfo attribute, int options); - 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); - } - /** * @param fileName * @param info * @param options */ - public static boolean setFileInfo(String fileName, IFileInfo info, int options) { + public static boolean putFileInfo(String fileName, IFileInfo info, int options) { if (isUnicode) return internalSetFileInfoW(Convert.toPlatformChars(fileName), info, options); return internalSetFileInfo(Convert.toPlatformBytes(fileName), info); @@ -166,7 +156,7 @@ * @return true if native library is available, and false * otherwise. */ - public static boolean usingNatives() { + public static boolean isUsingNatives() { return hasNatives; } } Index: src/org/eclipse/core/internal/filesystem/local/LocalFileNativesManager.java =================================================================== RCS file: src/org/eclipse/core/internal/filesystem/local/LocalFileNativesManager.java diff -N src/org/eclipse/core/internal/filesystem/local/LocalFileNativesManager.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/core/internal/filesystem/local/LocalFileNativesManager.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,57 @@ +/******************************************************************************* + * Copyright (c) 2010 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.core.internal.filesystem.local; + +import org.eclipse.core.filesystem.IFileInfo; +import org.eclipse.core.filesystem.provider.FileInfo; +import org.eclipse.core.internal.filesystem.Messages; +import org.eclipse.core.internal.filesystem.Policy; +import org.eclipse.core.internal.filesystem.local.unix.UnixFileNatives; +import org.eclipse.core.runtime.IStatus; + +/** + * Dispatches methods backed by native code to the appropriate platform specific + * implementation depending on a library provided by a fragment. + */ +public class LocalFileNativesManager { + + static { + if (!(UnixFileNatives.isUsingNatives() || LocalFileNatives.isUsingNatives())) + logMissingNativeLibrary(); + } + + private static void logMissingNativeLibrary() { + Policy.log(IStatus.INFO, Messages.couldNotNativeLibrary, new Exception(Messages.couldNotNativeLibrary)); + } + + public static int getSupportedAttributes() { + if (UnixFileNatives.isUsingNatives()) + return UnixFileNatives.getSupportedAttributes(); + return LocalFileNatives.attributes(); + } + + public static FileInfo fetchFileInfo(String fileName) { + if (UnixFileNatives.isUsingNatives()) + return UnixFileNatives.fetchFileInfo(fileName); + return LocalFileNatives.fetchFileInfo(fileName); + } + + public static boolean putFileInfo(String fileName, IFileInfo info, int options) { + if (UnixFileNatives.isUsingNatives()) + return UnixFileNatives.putFileInfo(fileName, info, options); + return LocalFileNatives.putFileInfo(fileName, info, options); + } + + public static boolean isUsingNatives() { + return UnixFileNatives.isUsingNatives() || LocalFileNatives.isUsingNatives(); + } + +} Index: src/org/eclipse/core/internal/filesystem/local/LocalFileSystem.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.core.filesystem/src/org/eclipse/core/internal/filesystem/local/LocalFileSystem.java,v retrieving revision 1.21 diff -u -r1.21 LocalFileSystem.java --- src/org/eclipse/core/internal/filesystem/local/LocalFileSystem.java 23 Nov 2009 11:20:20 -0000 1.21 +++ src/org/eclipse/core/internal/filesystem/local/LocalFileSystem.java 20 Jan 2010 13:15:41 -0000 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2009 IBM Corporation and others. + * Copyright (c) 2005, 2010 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -79,11 +79,11 @@ if (attributes != -1) return attributes; attributes = 0; - if (!LocalFileNatives.usingNatives()) + if (!LocalFileNativesManager.isUsingNatives()) return attributes; //try to query supported attributes from native lib impl - int nativeAttributes = LocalFileNatives.attributes(); + int nativeAttributes = LocalFileNativesManager.getSupportedAttributes(); if (nativeAttributes >= 0) { attributes = nativeAttributes; return attributes; Index: src/org/eclipse/core/internal/filesystem/local/unix/StructStat.java =================================================================== RCS file: src/org/eclipse/core/internal/filesystem/local/unix/StructStat.java diff -N src/org/eclipse/core/internal/filesystem/local/unix/StructStat.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/core/internal/filesystem/local/unix/StructStat.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,57 @@ +/******************************************************************************* + * Copyright (c) 2010 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.core.internal.filesystem.local.unix; + +import org.eclipse.core.filesystem.EFS; +import org.eclipse.core.filesystem.provider.FileInfo; + +/** + * This class mirrors relevant fields of native struct stat + * and is used by JNI calls wrapping OS file related functions. + */ +public class StructStat { + + public int st_mode; + public long st_size; + public long st_mtime; + public long st_flags; // Filled only on Mac OS X + + public FileInfo toFileInfo() { + FileInfo info = new FileInfo(); + info.setExists(true); + info.setLength(st_size); + info.setLastModified(st_mtime * 1000); + if ((st_mode & UnixFileFlags.S_IFMT) == UnixFileFlags.S_IFDIR) + info.setDirectory(true); + if ((st_flags & (UnixFileFlags.UF_IMMUTABLE | UnixFileFlags.SF_IMMUTABLE)) != 0) + info.setAttribute(EFS.ATTRIBUTE_IMMUTABLE, true); + if ((st_mode & UnixFileFlags.S_IRUSR) == 0) // Set to true in FileInfo constructor + info.setAttribute(EFS.ATTRIBUTE_OWNER_READ, false); + if ((st_mode & UnixFileFlags.S_IWUSR) == 0) // Set to true in FileInfo constructor + info.setAttribute(EFS.ATTRIBUTE_OWNER_WRITE, false); + if ((st_mode & UnixFileFlags.S_IXUSR) != 0) + info.setAttribute(EFS.ATTRIBUTE_OWNER_EXECUTE, true); + if ((st_mode & UnixFileFlags.S_IRGRP) != 0) + info.setAttribute(EFS.ATTRIBUTE_GROUP_READ, true); + if ((st_mode & UnixFileFlags.S_IWGRP) != 0) + info.setAttribute(EFS.ATTRIBUTE_GROUP_WRITE, true); + if ((st_mode & UnixFileFlags.S_IXGRP) != 0) + info.setAttribute(EFS.ATTRIBUTE_GROUP_EXECUTE, true); + if ((st_mode & UnixFileFlags.S_IROTH) != 0) + info.setAttribute(EFS.ATTRIBUTE_OTHER_READ, true); + if ((st_mode & UnixFileFlags.S_IWOTH) != 0) + info.setAttribute(EFS.ATTRIBUTE_OTHER_WRITE, true); + if ((st_mode & UnixFileFlags.S_IXOTH) != 0) + info.setAttribute(EFS.ATTRIBUTE_OTHER_EXECUTE, true); + return info; + } + +} Index: src/org/eclipse/core/internal/filesystem/local/unix/UnixFileFlags.java =================================================================== RCS file: src/org/eclipse/core/internal/filesystem/local/unix/UnixFileFlags.java diff -N src/org/eclipse/core/internal/filesystem/local/unix/UnixFileFlags.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/core/internal/filesystem/local/unix/UnixFileFlags.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,96 @@ +/******************************************************************************* + * Copyright (c) 2010 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.core.internal.filesystem.local.unix; + +public class UnixFileFlags { + + static { + PATH_MAX = UnixFileNatives.getFlag("PATH_MAX"); //$NON-NLS-1$ + S_IFMT = UnixFileNatives.getFlag("S_IFMT"); //$NON-NLS-1$ + S_IFLNK = UnixFileNatives.getFlag("S_IFLNK"); //$NON-NLS-1$ + S_IFDIR = UnixFileNatives.getFlag("S_IFDIR"); //$NON-NLS-1$ + S_IRUSR = UnixFileNatives.getFlag("S_IRUSR"); //$NON-NLS-1$ + S_IWUSR = UnixFileNatives.getFlag("S_IWUSR"); //$NON-NLS-1$ + S_IXUSR = UnixFileNatives.getFlag("S_IXUSR"); //$NON-NLS-1$ + S_IRGRP = UnixFileNatives.getFlag("S_IRGRP"); //$NON-NLS-1$ + S_IWGRP = UnixFileNatives.getFlag("S_IWGRP"); //$NON-NLS-1$ + S_IXGRP = UnixFileNatives.getFlag("S_IXGRP"); //$NON-NLS-1$ + S_IROTH = UnixFileNatives.getFlag("S_IROTH"); //$NON-NLS-1$ + S_IWOTH = UnixFileNatives.getFlag("S_IWOTH"); //$NON-NLS-1$ + S_IXOTH = UnixFileNatives.getFlag("S_IXOTH"); //$NON-NLS-1$ + UF_IMMUTABLE = UnixFileNatives.getFlag("UF_IMMUTABLE"); //$NON-NLS-1$ + SF_IMMUTABLE = UnixFileNatives.getFlag("SF_IMMUTABLE"); //$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; + + /** + * the file may not be changed + */ + public static final int UF_IMMUTABLE; + /** + * the file may not be changed + */ + public static final int SF_IMMUTABLE; + +} Index: src/org/eclipse/core/internal/filesystem/local/unix/UnixFileNatives.java =================================================================== RCS file: src/org/eclipse/core/internal/filesystem/local/unix/UnixFileNatives.java diff -N src/org/eclipse/core/internal/filesystem/local/unix/UnixFileNatives.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/core/internal/filesystem/local/unix/UnixFileNatives.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,178 @@ +/******************************************************************************* + * Copyright (c) 2010 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.core.internal.filesystem.local.unix; + +import java.io.UnsupportedEncodingException; +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; + +public abstract class UnixFileNatives { + + private static final String LIBRARY_NAME = "unixfile_1_0_0"; //$NON-NLS-1$ + private static final int UNICODE_SUPPORTED = 1 << 0; + private static final int CHFLAGS_SUPPORTED = 1 << 1; + + private static final boolean usingNatives; + private static final int libattr; + + static { + boolean _usingNatives = false; + int _libattr = 0; + try { + System.loadLibrary(LIBRARY_NAME); + _usingNatives = true; + _libattr = libattr(); + } catch (UnsatisfiedLinkError e) { + // Nothing to do + } finally { + usingNatives = _usingNatives; + libattr = _libattr; + } + } + + 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; + if (isSupported(CHFLAGS_SUPPORTED)) + ret |= EFS.ATTRIBUTE_IMMUTABLE; + return ret; + } + + public static FileInfo fetchFileInfo(String fileName) { + FileInfo info = null; + byte[] name = fileNameToBytes(fileName); + StructStat stat = new StructStat(); + if (lstat(name, stat) == 0) { + if ((stat.st_mode & UnixFileFlags.S_IFMT) == UnixFileFlags.S_IFLNK) { + if (stat(name, stat) == 0) + info = stat.toFileInfo(); + else + info = new FileInfo(); + info.setAttribute(EFS.ATTRIBUTE_SYMLINK, true); + byte target[] = new byte[UnixFileFlags.PATH_MAX]; + long length = readlink(name, target, target.length); + if (length > 0) + info.setStringAttribute(EFS.ATTRIBUTE_LINK_TARGET, bytesToFileName(target, (int) length)); + } else + info = stat.toFileInfo(); + } else + info = new FileInfo(); + return info; + } + + public static boolean putFileInfo(String fileName, IFileInfo info, int options) { + int code = 0; + byte[] name = fileNameToBytes(fileName); + if (name == null) + return false; + + // In case uchg flag is to be removed do it before calling chmod + if (!info.getAttribute(EFS.ATTRIBUTE_IMMUTABLE) && isSupported(CHFLAGS_SUPPORTED)) { + StructStat stat = new StructStat(); + if (stat(name, stat) == 0) { + long flags = stat.st_flags; + flags &= ~UnixFileFlags.SF_IMMUTABLE; + flags &= ~UnixFileFlags.UF_IMMUTABLE; + code |= chflags(name, (int) flags); + } + } + + // Change permissions + int mode = 0; + if (info.getAttribute(EFS.ATTRIBUTE_OWNER_READ)) + mode |= UnixFileFlags.S_IRUSR; + if (info.getAttribute(EFS.ATTRIBUTE_OWNER_WRITE)) + mode |= UnixFileFlags.S_IWUSR; + if (info.getAttribute(EFS.ATTRIBUTE_OWNER_EXECUTE)) + mode |= UnixFileFlags.S_IXUSR; + if (info.getAttribute(EFS.ATTRIBUTE_GROUP_READ)) + mode |= UnixFileFlags.S_IRGRP; + if (info.getAttribute(EFS.ATTRIBUTE_GROUP_WRITE)) + mode |= UnixFileFlags.S_IWGRP; + if (info.getAttribute(EFS.ATTRIBUTE_GROUP_EXECUTE)) + mode |= UnixFileFlags.S_IXGRP; + if (info.getAttribute(EFS.ATTRIBUTE_OTHER_READ)) + mode |= UnixFileFlags.S_IROTH; + if (info.getAttribute(EFS.ATTRIBUTE_OTHER_WRITE)) + mode |= UnixFileFlags.S_IWOTH; + if (info.getAttribute(EFS.ATTRIBUTE_OTHER_EXECUTE)) + mode |= UnixFileFlags.S_IXOTH; + code |= chmod(name, mode); + + // In case uchg flag is to be added do it after calling chmod + if (info.getAttribute(EFS.ATTRIBUTE_IMMUTABLE) && isSupported(CHFLAGS_SUPPORTED)) { + StructStat stat = new StructStat(); + if (stat(name, stat) == 0) { + long flags = stat.st_flags; + flags |= UnixFileFlags.SF_IMMUTABLE; + code |= chflags(name, UnixFileFlags.UF_IMMUTABLE); + } + } + return code == 0; + } + + public static boolean isUsingNatives() { + return usingNatives; + } + + public static int getErrno() { + return errno(); + } + + public static int getFlag(String flag) { + if (!usingNatives) + return -1; + try { + return getflag(flag.getBytes("ASCII")); //$NON-NLS-1$ + } catch (UnsupportedEncodingException e) { + // Should never happen + return -1; + } + } + + private static byte[] fileNameToBytes(String fileName) { + if (isSupported(UNICODE_SUPPORTED)) + return tounicode(fileName.toCharArray()); + return Convert.toPlatformBytes(fileName); + } + + private static String bytesToFileName(byte[] buf, int length) { + if (isSupported(UNICODE_SUPPORTED)) + return new String(buf, 0, length); + return Convert.fromPlatformBytes(buf, length); + } + + private static boolean isSupported(int attr) { + return (libattr & attr) != 0; + } + + private static final native int chmod(byte[] path, int mode); + + private static final native int chflags(byte[] path, int flags); + + private static final native int stat(byte[] path, StructStat buf); + + private static final native int lstat(byte[] path, StructStat buf); + + private static final native long readlink(byte[] path, byte[] buf, long bufsiz); + + private static final native int errno(); + + private static final native int libattr(); + + private static final native byte[] tounicode(char[] buf); + + private static final native int getflag(byte[] buf); + +} Index: src/org/eclipse/core/internal/filesystem/messages.properties =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.core.filesystem/src/org/eclipse/core/internal/filesystem/messages.properties,v retrieving revision 1.5 diff -u -r1.5 messages.properties --- src/org/eclipse/core/internal/filesystem/messages.properties 19 Oct 2006 22:00:40 -0000 1.5 +++ src/org/eclipse/core/internal/filesystem/messages.properties 20 Jan 2010 13:15:42 -0000 @@ -1,5 +1,5 @@ ############################################################################### -# Copyright (c) 2005, 2006 IBM Corporation and others. +# Copyright (c) 2005, 2010 IBM Corporation and others. # All rights reserved. This program and the accompanying materials # are made available under the terms of the Eclipse Public License v1.0 # which accompanies this distribution, and is available at @@ -13,7 +13,7 @@ copying = Copying: {0}. couldnotDelete = Could not delete: {0}. couldnotDeleteReadOnly = Could not delete read-only file: {0}. -couldNotLoadLibrary = Could not load library: {0}. This library provides platform-specific optimizations for certain file system operations. This library is not present on all platforms, so this may not be an error. The resources plug-in will safely fall back to using java.io.File functionality. +couldNotNativeLibrary== Could not load library providing platform-specific optimizations for certain file system operations. This library is not present on all platforms, so this may not be an error. The resources plug-in will safely fall back to using java.io.File functionality. couldNotMove = Could not move: {0}. couldNotRead = Could not read file: {0}. couldNotWrite = Could not write file: {0}. #P org.eclipse.core.tests.resources Index: src/org/eclipse/core/tests/filesystem/FileStoreTest.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.core.tests.resources/src/org/eclipse/core/tests/filesystem/FileStoreTest.java,v retrieving revision 1.5 diff -u -r1.5 FileStoreTest.java --- src/org/eclipse/core/tests/filesystem/FileStoreTest.java 20 May 2009 23:50:55 -0000 1.5 +++ src/org/eclipse/core/tests/filesystem/FileStoreTest.java 20 Jan 2010 13:15:44 -0000 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2008 IBM Corporation and others. + * Copyright (c) 2000, 2010 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -51,7 +51,7 @@ private IFileStore createDir(String string, boolean clear) throws CoreException { return createDir(EFS.getFileSystem(EFS.SCHEME_FILE).getStore(new Path(string)), clear); } - + /** * Tests behaviour of IFileStore#fetchInfo when underlying file system * throws exceptions. @@ -68,7 +68,7 @@ //no-arg fetch info should return non-existent file IFileInfo info = broken.fetchInfo(); assertTrue("1.0", !info.exists()); - + //two-arg fetchInfo should throw exception try { info = broken.fetchInfo(EFS.NONE, getMonitor()); @@ -483,43 +483,86 @@ } public void testReadOnly() throws CoreException { - // We need to know whether or not we can unset the read-only flag - // in order to perform this test. - if (!isReadOnlySupported()) + testAttribute(EFS.ATTRIBUTE_READ_ONLY); + } + + public void testPermissionsEnabled() { + String os = Platform.getOS(); + String arch = Platform.getOSArch(); + if (Platform.OS_LINUX.equals(os) || (Platform.OS_SOLARIS.equals(os) && Platform.ARCH_SPARC.equals(arch)) || Platform.OS_MACOSX.equals(os) || Platform.OS_AIX.equals(os)) { + assertTrue(isAttributeSupported(EFS.ATTRIBUTE_OWNER_READ)); + assertTrue(isAttributeSupported(EFS.ATTRIBUTE_OWNER_WRITE)); + assertTrue(isAttributeSupported(EFS.ATTRIBUTE_OWNER_EXECUTE)); + assertTrue(isAttributeSupported(EFS.ATTRIBUTE_GROUP_READ)); + assertTrue(isAttributeSupported(EFS.ATTRIBUTE_GROUP_WRITE)); + assertTrue(isAttributeSupported(EFS.ATTRIBUTE_GROUP_EXECUTE)); + assertTrue(isAttributeSupported(EFS.ATTRIBUTE_OTHER_READ)); + assertTrue(isAttributeSupported(EFS.ATTRIBUTE_OTHER_WRITE)); + assertTrue(isAttributeSupported(EFS.ATTRIBUTE_OTHER_EXECUTE)); + } else { + assertFalse(isAttributeSupported(EFS.ATTRIBUTE_OWNER_READ)); + assertFalse(isAttributeSupported(EFS.ATTRIBUTE_OWNER_WRITE)); + assertFalse(isAttributeSupported(EFS.ATTRIBUTE_OWNER_EXECUTE)); + assertFalse(isAttributeSupported(EFS.ATTRIBUTE_GROUP_READ)); + assertFalse(isAttributeSupported(EFS.ATTRIBUTE_GROUP_WRITE)); + assertFalse(isAttributeSupported(EFS.ATTRIBUTE_GROUP_EXECUTE)); + assertFalse(isAttributeSupported(EFS.ATTRIBUTE_OTHER_READ)); + assertFalse(isAttributeSupported(EFS.ATTRIBUTE_OTHER_WRITE)); + assertFalse(isAttributeSupported(EFS.ATTRIBUTE_OTHER_EXECUTE)); + } + } + + public void testPermissions() throws CoreException { + testAttribute(EFS.ATTRIBUTE_OWNER_READ); + testAttribute(EFS.ATTRIBUTE_OWNER_WRITE); + testAttribute(EFS.ATTRIBUTE_OWNER_EXECUTE); + testAttribute(EFS.ATTRIBUTE_GROUP_READ); + testAttribute(EFS.ATTRIBUTE_GROUP_WRITE); + testAttribute(EFS.ATTRIBUTE_GROUP_EXECUTE); + testAttribute(EFS.ATTRIBUTE_OTHER_READ); + testAttribute(EFS.ATTRIBUTE_OTHER_WRITE); + testAttribute(EFS.ATTRIBUTE_OTHER_EXECUTE); + } + + private void testAttribute(int attribute) throws CoreException { + if (!isAttributeSupported(attribute)) return; IPath root = getWorkspace().getRoot().getLocation().append("" + new Date().getTime()); IFileStore targetFolder = createDir(root.toString(), true); - IFileStore targetFile = targetFolder.getChild("targetFile"); - createFileInFileSystem(targetFile); + try { + IFileStore targetFile = targetFolder.getChild("targetFile"); + createFileInFileSystem(targetFile); - // file - assertTrue("1.0", !targetFile.fetchInfo().getAttribute(EFS.ATTRIBUTE_READ_ONLY)); - setReadOnly(targetFile, true); - assertTrue("1.2", targetFile.fetchInfo().getAttribute(EFS.ATTRIBUTE_READ_ONLY)); - setReadOnly(targetFile, false); - assertTrue("1.4", !targetFile.fetchInfo().getAttribute(EFS.ATTRIBUTE_READ_ONLY)); - - // folder - assertTrue("2.0", !targetFolder.fetchInfo().getAttribute(EFS.ATTRIBUTE_READ_ONLY)); - setReadOnly(targetFolder, true); - assertTrue("2.2", targetFolder.fetchInfo().getAttribute(EFS.ATTRIBUTE_READ_ONLY)); - setReadOnly(targetFolder, false); - assertTrue("2.4", !targetFolder.fetchInfo().getAttribute(EFS.ATTRIBUTE_READ_ONLY)); + // file + boolean init = targetFile.fetchInfo().getAttribute(attribute); + setAttribute(targetFile, attribute, !init); + assertTrue("1.2", targetFile.fetchInfo().getAttribute(attribute) != init); + setAttribute(targetFile, attribute, init); + assertTrue("1.4", targetFile.fetchInfo().getAttribute(attribute) == init); + + // folder + init = targetFolder.fetchInfo().getAttribute(attribute); + setAttribute(targetFolder, attribute, !init); + assertTrue("2.2", targetFolder.fetchInfo().getAttribute(attribute) != init); + setAttribute(targetFolder, attribute, init); + assertTrue("2.4", targetFolder.fetchInfo().getAttribute(attribute) == init); - /* remove trash */ - targetFolder.delete(EFS.NONE, null); + } finally { + /* remove trash */ + targetFolder.delete(EFS.NONE, null); + } } - + public void testGetFileStore() throws Exception { // create files File file = getTempDir().append("test.txt").toFile(); file.createNewFile(); assertTrue("1.0", file.exists()); - + IFileStore tempStore = createDir(getTempDir().append("temp").toString(), true); createDir(getTempDir().append("temp/temp2").toString(), true); - + file = getTempDir().append("temp/temp2/test.txt").toFile(); file.createNewFile(); assertTrue("2.0", file.exists()); @@ -532,19 +575,19 @@ IFileInfo info = relativeStore.fetchInfo(); assertNotNull("4.0", info); assertTrue("5.0", info.exists()); - + // check the parent and self reference relativePath = new Path(".././test.txt"); - + relativeStore = tempStore.getFileStore(relativePath); assertNotNull("6.0", relativeStore); info = relativeStore.fetchInfo(); assertNotNull("7.0", info); assertTrue("8.0", info.exists()); - + // check the a path with no parent and self references relativePath = new Path("temp2/test.txt"); - + relativeStore = tempStore.getFileStore(relativePath); assertNotNull("9.0", relativeStore); info = relativeStore.fetchInfo(); Index: src/org/eclipse/core/tests/resources/ResourceTest.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.core.tests.resources/src/org/eclipse/core/tests/resources/ResourceTest.java,v retrieving revision 1.24 diff -u -r1.24 ResourceTest.java --- src/org/eclipse/core/tests/resources/ResourceTest.java 25 Jan 2008 23:17:20 -0000 1.24 +++ src/org/eclipse/core/tests/resources/ResourceTest.java 20 Jan 2010 13:15:44 -0000 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2008 IBM Corporation and others. + * Copyright (c) 2000, 2010 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -868,6 +868,17 @@ return null; } + protected void setAttribute(IFileStore target, int attribute, boolean value) { + assertTrue("setAttribute.1", isAttributeSupported(attribute)); + IFileInfo fileInfo = target.fetchInfo(); + fileInfo.setAttribute(attribute, value); + try { + target.putInfo(fileInfo, EFS.SET_ATTRIBUTES, null); + } catch (CoreException e) { + fail("ResourceTest#setAttribute", e); + } + } + protected void setReadOnly(IFileStore target, boolean value) { assertTrue("setReadOnly.1", isReadOnlySupported()); IFileInfo fileInfo = target.fetchInfo();