Use the system character encoding to encode file names before passing them to the native code.

This commit is contained in:
Adam Murdoch
2012-08-12 13:13:11 +10:00
parent 058df967a4
commit 1878bd9ff0
7 changed files with 79 additions and 50 deletions

View File

@@ -114,3 +114,5 @@ You can run `$INSTALL_DIR/bin/native-platform` to run the test application.
* Improve error message when unsupported capability is used. * Improve error message when unsupported capability is used.
* Initial release. * Initial release.
* Use fully decomposed form for unicode file names on hfs+ filesystems. * Use fully decomposed form for unicode file names on hfs+ filesystems.
* Handle string encoding for file system details
* Handle string encoding for system info

View File

@@ -17,5 +17,5 @@ void mark_failed_with_code(JNIEnv *env, const char* message, int error_code, job
JNIEXPORT jint JNICALL JNIEXPORT jint JNICALL
Java_net_rubygrapefruit_platform_internal_jni_NativeLibraryFunctions_getVersion(JNIEnv *env, jclass target) { Java_net_rubygrapefruit_platform_internal_jni_NativeLibraryFunctions_getVersion(JNIEnv *env, jclass target) {
return 5; return 6;
} }

View File

@@ -56,21 +56,21 @@ Java_net_rubygrapefruit_platform_internal_jni_NativeLibraryFunctions_getSystemIn
*/ */
JNIEXPORT void JNICALL JNIEXPORT void JNICALL
Java_net_rubygrapefruit_platform_internal_jni_PosixFileFunctions_chmod(JNIEnv *env, jclass target, jstring path, jint mode, jobject result) { Java_net_rubygrapefruit_platform_internal_jni_PosixFileFunctions_chmod(JNIEnv *env, jclass target, jbyteArray path, jint mode, jobject result) {
const char* pathUtf8 = env->GetStringUTFChars(path, NULL); jbyte* pathUtf8 = env->GetByteArrayElements(path, NULL);
int retval = chmod(pathUtf8, mode); int retval = chmod((const char*)pathUtf8, mode);
env->ReleaseStringUTFChars(path, pathUtf8); env->ReleaseByteArrayElements(path, pathUtf8, JNI_ABORT);
if (retval != 0) { if (retval != 0) {
mark_failed_with_errno(env, "could not chmod file", result); mark_failed_with_errno(env, "could not chmod file", result);
} }
} }
JNIEXPORT void JNICALL JNIEXPORT void JNICALL
Java_net_rubygrapefruit_platform_internal_jni_PosixFileFunctions_stat(JNIEnv *env, jclass target, jstring path, jobject dest, jobject result) { Java_net_rubygrapefruit_platform_internal_jni_PosixFileFunctions_stat(JNIEnv *env, jclass target, jbyteArray path, jobject dest, jobject result) {
struct stat fileInfo; struct stat fileInfo;
const char* pathUtf8 = env->GetStringUTFChars(path, NULL); jbyte* pathUtf8 = env->GetByteArrayElements(path, NULL);
int retval = stat(pathUtf8, &fileInfo); int retval = stat((const char*)pathUtf8, &fileInfo);
env->ReleaseStringUTFChars(path, pathUtf8); env->ReleaseByteArrayElements(path, pathUtf8, JNI_ABORT);
if (retval != 0) { if (retval != 0) {
mark_failed_with_errno(env, "could not stat file", result); mark_failed_with_errno(env, "could not stat file", result);
return; return;

View File

@@ -1,29 +1,57 @@
package net.rubygrapefruit.platform.internal; package net.rubygrapefruit.platform.internal;
import net.rubygrapefruit.platform.NativeException; import net.rubygrapefruit.platform.NativeException;
import net.rubygrapefruit.platform.PosixFile; import net.rubygrapefruit.platform.PosixFile;
import net.rubygrapefruit.platform.internal.jni.PosixFileFunctions; import net.rubygrapefruit.platform.internal.jni.NativeLibraryFunctions;
import net.rubygrapefruit.platform.internal.jni.PosixFileFunctions;
import java.io.File;
import java.io.File;
public class DefaultPosixFile implements PosixFile { import java.io.UnsupportedEncodingException;
@Override
public void setMode(File file, int perms) { public class DefaultPosixFile implements PosixFile {
FunctionResult result = new FunctionResult(); private final String characterEncoding;
PosixFileFunctions.chmod(file.getPath(), perms, result);
if (result.isFailed()) { public DefaultPosixFile() {
throw new NativeException(String.format("Could not set UNIX mode on %s: %s", file, result.getMessage())); MutableSystemInfo systemInfo = new MutableSystemInfo();
} FunctionResult result = new FunctionResult();
} NativeLibraryFunctions.getSystemInfo(systemInfo, result);
if (result.isFailed()) {
@Override throw new NativeException(String.format("Could not fetch system information: %s",
public int getMode(File file) { result.getMessage()));
FunctionResult result = new FunctionResult(); }
FileStat stat = new FileStat(); this.characterEncoding = systemInfo.characterEncoding;
PosixFileFunctions.stat(file.getPath(), stat, result); }
if (result.isFailed()) {
throw new NativeException(String.format("Could not get UNIX mode on %s: %s", file, result.getMessage())); @Override
} public void setMode(File file, int perms) {
return stat.mode; FunctionResult result = new FunctionResult();
} PosixFileFunctions.chmod(encode(file), perms, result);
} if (result.isFailed()) {
throw new NativeException(String.format("Could not set UNIX mode on %s: %s", file, result.getMessage()));
}
}
@Override
public int getMode(File file) {
FunctionResult result = new FunctionResult();
FileStat stat = new FileStat();
PosixFileFunctions.stat(encode(file), stat, result);
if (result.isFailed()) {
throw new NativeException(String.format("Could not get UNIX mode on %s: %s", file, result.getMessage()));
}
return stat.mode;
}
private byte[] encode(File file) {
byte[] encodedName;
try {
encodedName = file.getPath().getBytes(characterEncoding);
} catch (UnsupportedEncodingException e) {
throw new NativeException(String.format("Could not encode path for file '%s' using encoding %s.", file.getName(), characterEncoding));
}
byte[] buffer = new byte[encodedName.length + 1];
System.arraycopy(encodedName, 0, buffer, 0, encodedName.length);
buffer[buffer.length - 1] = 0;
return buffer;
}
}

View File

@@ -85,7 +85,6 @@ public abstract class Platform {
throw new NativeException(String.format("Could not fetch system information: %s", throw new NativeException(String.format("Could not fetch system information: %s",
result.getMessage())); result.getMessage()));
} }
System.out.println("=> CHARACTER ENCODING: " + systemInfo.characterEncoding);
return type.cast(systemInfo); return type.cast(systemInfo);
} }
return super.get(type); return super.get(type);

View File

@@ -4,7 +4,7 @@ import net.rubygrapefruit.platform.internal.FunctionResult;
import net.rubygrapefruit.platform.internal.MutableSystemInfo; import net.rubygrapefruit.platform.internal.MutableSystemInfo;
public class NativeLibraryFunctions { public class NativeLibraryFunctions {
public static final int VERSION = 5; public static final int VERSION = 6;
public static native int getVersion(); public static native int getVersion();

View File

@@ -1,10 +1,10 @@
package net.rubygrapefruit.platform.internal.jni; package net.rubygrapefruit.platform.internal.jni;
import net.rubygrapefruit.platform.internal.FileStat; import net.rubygrapefruit.platform.internal.FileStat;
import net.rubygrapefruit.platform.internal.FunctionResult; import net.rubygrapefruit.platform.internal.FunctionResult;
public class PosixFileFunctions { public class PosixFileFunctions {
public static native void chmod(String file, int perms, FunctionResult result); public static native void chmod(byte[] file, int perms, FunctionResult result);
public static native void stat(String file, FileStat stat, FunctionResult result); public static native void stat(byte[] file, FileStat stat, FunctionResult result);
} }