Use the system character encoding to encode file names before passing them to the native code.
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -2,15 +2,30 @@ 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.NativeLibraryFunctions;
|
||||||
import net.rubygrapefruit.platform.internal.jni.PosixFileFunctions;
|
import net.rubygrapefruit.platform.internal.jni.PosixFileFunctions;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
|
||||||
public class DefaultPosixFile implements PosixFile {
|
public class DefaultPosixFile implements PosixFile {
|
||||||
|
private final String characterEncoding;
|
||||||
|
|
||||||
|
public DefaultPosixFile() {
|
||||||
|
MutableSystemInfo systemInfo = new MutableSystemInfo();
|
||||||
|
FunctionResult result = new FunctionResult();
|
||||||
|
NativeLibraryFunctions.getSystemInfo(systemInfo, result);
|
||||||
|
if (result.isFailed()) {
|
||||||
|
throw new NativeException(String.format("Could not fetch system information: %s",
|
||||||
|
result.getMessage()));
|
||||||
|
}
|
||||||
|
this.characterEncoding = systemInfo.characterEncoding;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setMode(File file, int perms) {
|
public void setMode(File file, int perms) {
|
||||||
FunctionResult result = new FunctionResult();
|
FunctionResult result = new FunctionResult();
|
||||||
PosixFileFunctions.chmod(file.getPath(), perms, result);
|
PosixFileFunctions.chmod(encode(file), perms, result);
|
||||||
if (result.isFailed()) {
|
if (result.isFailed()) {
|
||||||
throw new NativeException(String.format("Could not set UNIX mode on %s: %s", file, result.getMessage()));
|
throw new NativeException(String.format("Could not set UNIX mode on %s: %s", file, result.getMessage()));
|
||||||
}
|
}
|
||||||
@@ -20,10 +35,23 @@ public class DefaultPosixFile implements PosixFile {
|
|||||||
public int getMode(File file) {
|
public int getMode(File file) {
|
||||||
FunctionResult result = new FunctionResult();
|
FunctionResult result = new FunctionResult();
|
||||||
FileStat stat = new FileStat();
|
FileStat stat = new FileStat();
|
||||||
PosixFileFunctions.stat(file.getPath(), stat, result);
|
PosixFileFunctions.stat(encode(file), stat, result);
|
||||||
if (result.isFailed()) {
|
if (result.isFailed()) {
|
||||||
throw new NativeException(String.format("Could not get UNIX mode on %s: %s", file, result.getMessage()));
|
throw new NativeException(String.format("Could not get UNIX mode on %s: %s", file, result.getMessage()));
|
||||||
}
|
}
|
||||||
return stat.mode;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ 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);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user