- Changed PosixFileFunctions to pass Strings to JNI methods, and use java_to_char() to encode as C char string.
- Don't need to pass system encoding back up to Java as part of system info.
This commit is contained in:
@@ -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 8;
|
return 9;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ void mark_failed_with_errno(JNIEnv *env, const char* message, jobject result) {
|
|||||||
|
|
||||||
char* java_to_char(JNIEnv *env, jstring string, jobject result) {
|
char* java_to_char(JNIEnv *env, jstring string, jobject result) {
|
||||||
// TODO - share this code with nnn_getSystemInfo() below
|
// TODO - share this code with nnn_getSystemInfo() below
|
||||||
|
// Empty string means load locale from environment.
|
||||||
locale_t locale = newlocale(LC_CTYPE_MASK, "", NULL);
|
locale_t locale = newlocale(LC_CTYPE_MASK, "", NULL);
|
||||||
if (locale == NULL) {
|
if (locale == NULL) {
|
||||||
mark_failed_with_message(env, "could not create locale", result);
|
mark_failed_with_message(env, "could not create locale", result);
|
||||||
@@ -47,6 +48,7 @@ char* java_to_char(JNIEnv *env, jstring string, jobject result) {
|
|||||||
|
|
||||||
jstring char_to_java(JNIEnv* env, const char* chars, jobject result) {
|
jstring char_to_java(JNIEnv* env, const char* chars, jobject result) {
|
||||||
// TODO - share this code with nnn_getSystemInfo() below
|
// TODO - share this code with nnn_getSystemInfo() below
|
||||||
|
// Empty string means load locale from environment.
|
||||||
locale_t locale = newlocale(LC_CTYPE_MASK, "", NULL);
|
locale_t locale = newlocale(LC_CTYPE_MASK, "", NULL);
|
||||||
if (locale == NULL) {
|
if (locale == NULL) {
|
||||||
mark_failed_with_message(env, "could not create locale", result);
|
mark_failed_with_message(env, "could not create locale", result);
|
||||||
@@ -69,17 +71,6 @@ JNIEXPORT void JNICALL
|
|||||||
Java_net_rubygrapefruit_platform_internal_jni_NativeLibraryFunctions_getSystemInfo(JNIEnv *env, jclass target, jobject info, jobject result) {
|
Java_net_rubygrapefruit_platform_internal_jni_NativeLibraryFunctions_getSystemInfo(JNIEnv *env, jclass target, jobject info, jobject result) {
|
||||||
jclass infoClass = env->GetObjectClass(info);
|
jclass infoClass = env->GetObjectClass(info);
|
||||||
|
|
||||||
// Empty string means load locale from environment.
|
|
||||||
locale_t locale = newlocale(LC_CTYPE_MASK, "", NULL);
|
|
||||||
if (locale == NULL) {
|
|
||||||
mark_failed_with_message(env, "could not create locale", result);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
jfieldID characterEncodingField = env->GetFieldID(infoClass, "characterEncoding", "Ljava/lang/String;");
|
|
||||||
env->SetObjectField(info, characterEncodingField, env->NewStringUTF(nl_langinfo_l(CODESET, locale)));
|
|
||||||
freelocale(locale);
|
|
||||||
|
|
||||||
struct utsname machine_info;
|
struct utsname machine_info;
|
||||||
if (uname(&machine_info) != 0) {
|
if (uname(&machine_info) != 0) {
|
||||||
mark_failed_with_errno(env, "could not query machine details", result);
|
mark_failed_with_errno(env, "could not query machine details", result);
|
||||||
@@ -99,21 +90,27 @@ 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, jbyteArray path, jint mode, jobject result) {
|
Java_net_rubygrapefruit_platform_internal_jni_PosixFileFunctions_chmod(JNIEnv *env, jclass target, jstring path, jint mode, jobject result) {
|
||||||
jbyte* pathUtf8 = env->GetByteArrayElements(path, NULL);
|
char* pathStr = java_to_char(env, path, result);
|
||||||
int retval = chmod((const char*)pathUtf8, mode);
|
if (pathStr == NULL) {
|
||||||
env->ReleaseByteArrayElements(path, pathUtf8, JNI_ABORT);
|
return;
|
||||||
|
}
|
||||||
|
int retval = chmod(pathStr, mode);
|
||||||
|
free(pathStr);
|
||||||
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, jbyteArray path, jobject dest, jobject result) {
|
Java_net_rubygrapefruit_platform_internal_jni_PosixFileFunctions_stat(JNIEnv *env, jclass target, jstring path, jobject dest, jobject result) {
|
||||||
struct stat fileInfo;
|
struct stat fileInfo;
|
||||||
jbyte* pathUtf8 = env->GetByteArrayElements(path, NULL);
|
char* pathStr = java_to_char(env, path, result);
|
||||||
int retval = stat((const char*)pathUtf8, &fileInfo);
|
if (pathStr == NULL) {
|
||||||
env->ReleaseByteArrayElements(path, pathUtf8, JNI_ABORT);
|
return;
|
||||||
|
}
|
||||||
|
int retval = stat(pathStr, &fileInfo);
|
||||||
|
free(pathStr);
|
||||||
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;
|
||||||
@@ -124,37 +121,47 @@ Java_net_rubygrapefruit_platform_internal_jni_PosixFileFunctions_stat(JNIEnv *en
|
|||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT void JNICALL
|
JNIEXPORT void JNICALL
|
||||||
Java_net_rubygrapefruit_platform_internal_jni_PosixFileFunctions_symlink(JNIEnv *env, jclass target, jbyteArray path, jbyteArray contents, jobject result) {
|
Java_net_rubygrapefruit_platform_internal_jni_PosixFileFunctions_symlink(JNIEnv *env, jclass target, jstring path, jstring contents, jobject result) {
|
||||||
jbyte* pathUtf8 = env->GetByteArrayElements(path, NULL);
|
char* pathStr = java_to_char(env, path, result);
|
||||||
jbyte* contentsUtf8 = env->GetByteArrayElements(contents, NULL);
|
if (pathStr == NULL) {
|
||||||
int retval = symlink((const char*)contentsUtf8, (const char*)pathUtf8);
|
return;
|
||||||
env->ReleaseByteArrayElements(path, pathUtf8, JNI_ABORT);
|
}
|
||||||
env->ReleaseByteArrayElements(contents, contentsUtf8, JNI_ABORT);
|
char* contentStr = java_to_char(env, contents, result);
|
||||||
|
if (contentStr == NULL) {
|
||||||
|
free(pathStr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int retval = symlink(contentStr, pathStr);
|
||||||
|
free(contentStr);
|
||||||
|
free(pathStr);
|
||||||
if (retval != 0) {
|
if (retval != 0) {
|
||||||
mark_failed_with_errno(env, "could not symlink", result);
|
mark_failed_with_errno(env, "could not symlink", result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT jstring JNICALL
|
JNIEXPORT jstring JNICALL
|
||||||
Java_net_rubygrapefruit_platform_internal_jni_PosixFileFunctions_readlink(JNIEnv *env, jclass target, jbyteArray path, jobject result) {
|
Java_net_rubygrapefruit_platform_internal_jni_PosixFileFunctions_readlink(JNIEnv *env, jclass target, jstring path, jobject result) {
|
||||||
struct stat link_info;
|
struct stat link_info;
|
||||||
jbyte* pathUtf8 = env->GetByteArrayElements(path, NULL);
|
char* pathStr = java_to_char(env, path, result);
|
||||||
int retval = lstat((const char*)pathUtf8, &link_info);
|
if (pathStr == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
int retval = lstat(pathStr, &link_info);
|
||||||
if (retval != 0) {
|
if (retval != 0) {
|
||||||
env->ReleaseByteArrayElements(path, pathUtf8, JNI_ABORT);
|
free(pathStr);
|
||||||
mark_failed_with_errno(env, "could not lstat file", result);
|
mark_failed_with_errno(env, "could not lstat file", result);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
char* contents = (char*)malloc(link_info.st_size + 1);
|
char* contents = (char*)malloc(link_info.st_size + 1);
|
||||||
if (contents == NULL) {
|
if (contents == NULL) {
|
||||||
env->ReleaseByteArrayElements(path, pathUtf8, JNI_ABORT);
|
free(pathStr);
|
||||||
mark_failed_with_message(env, "could not create array", result);
|
mark_failed_with_message(env, "could not create array", result);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
retval = readlink((const char*)pathUtf8, contents, link_info.st_size);
|
retval = readlink(pathStr, contents, link_info.st_size);
|
||||||
env->ReleaseByteArrayElements(path, pathUtf8, JNI_ABORT);
|
free(pathStr);
|
||||||
if (retval < 0) {
|
if (retval < 0) {
|
||||||
free(contents);
|
free(contents);
|
||||||
mark_failed_with_errno(env, "could not readlink", result);
|
mark_failed_with_errno(env, "could not readlink", result);
|
||||||
|
|||||||
@@ -5,19 +5,11 @@ import net.rubygrapefruit.platform.PosixFile;
|
|||||||
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() {
|
|
||||||
DefaultSystemInfo systemInfo = new DefaultSystemInfo();
|
|
||||||
this.characterEncoding = systemInfo.getCharacterEncoding();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMode(File file, int perms) {
|
public void setMode(File file, int perms) {
|
||||||
FunctionResult result = new FunctionResult();
|
FunctionResult result = new FunctionResult();
|
||||||
PosixFileFunctions.chmod(encode(file), perms, result);
|
PosixFileFunctions.chmod(file.getPath(), 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()));
|
||||||
}
|
}
|
||||||
@@ -26,7 +18,7 @@ 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(encode(file), stat, result);
|
PosixFileFunctions.stat(file.getPath(), 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()));
|
||||||
}
|
}
|
||||||
@@ -36,7 +28,7 @@ public class DefaultPosixFile implements PosixFile {
|
|||||||
@Override
|
@Override
|
||||||
public String readLink(File link) throws NativeException {
|
public String readLink(File link) throws NativeException {
|
||||||
FunctionResult result = new FunctionResult();
|
FunctionResult result = new FunctionResult();
|
||||||
String contents = PosixFileFunctions.readlink(encode(link), result);
|
String contents = PosixFileFunctions.readlink(link.getPath(), result);
|
||||||
if (result.isFailed()) {
|
if (result.isFailed()) {
|
||||||
throw new NativeException(String.format("Could not read symlink %s: %s", link, result.getMessage()));
|
throw new NativeException(String.format("Could not read symlink %s: %s", link, result.getMessage()));
|
||||||
}
|
}
|
||||||
@@ -46,26 +38,9 @@ public class DefaultPosixFile implements PosixFile {
|
|||||||
@Override
|
@Override
|
||||||
public void symlink(File link, String contents) throws NativeException {
|
public void symlink(File link, String contents) throws NativeException {
|
||||||
FunctionResult result = new FunctionResult();
|
FunctionResult result = new FunctionResult();
|
||||||
PosixFileFunctions.symlink(encode(link), encode(contents), result);
|
PosixFileFunctions.symlink(link.getPath(), contents, result);
|
||||||
if (result.isFailed()) {
|
if (result.isFailed()) {
|
||||||
throw new NativeException(String.format("Could not create symlink %s: %s", link, result.getMessage()));
|
throw new NativeException(String.format("Could not create symlink %s: %s", link, result.getMessage()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private byte[] encode(File file) {
|
|
||||||
return encode(file.getPath());
|
|
||||||
}
|
|
||||||
|
|
||||||
private byte[] encode(String path) {
|
|
||||||
byte[] encodedName;
|
|
||||||
try {
|
|
||||||
encodedName = path.getBytes(characterEncoding);
|
|
||||||
} catch (UnsupportedEncodingException e) {
|
|
||||||
throw new NativeException(String.format("Could not encode path '%s' using encoding %s.", path, characterEncoding), e);
|
|
||||||
}
|
|
||||||
byte[] buffer = new byte[encodedName.length + 1];
|
|
||||||
System.arraycopy(encodedName, 0, buffer, 0, encodedName.length);
|
|
||||||
buffer[buffer.length - 1] = 0;
|
|
||||||
return buffer;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,8 +30,4 @@ public class DefaultSystemInfo implements SystemInfo {
|
|||||||
public String getMachineArchitecture() {
|
public String getMachineArchitecture() {
|
||||||
return systemInfo.getMachineArchitecture();
|
return systemInfo.getMachineArchitecture();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getCharacterEncoding() {
|
|
||||||
return systemInfo.characterEncoding;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import net.rubygrapefruit.platform.SystemInfo;
|
|||||||
public class MutableSystemInfo implements SystemInfo {
|
public class MutableSystemInfo implements SystemInfo {
|
||||||
public String osName;
|
public String osName;
|
||||||
public String osVersion;
|
public String osVersion;
|
||||||
public String characterEncoding;
|
|
||||||
public String machineArchitecture;
|
public String machineArchitecture;
|
||||||
|
|
||||||
public String getKernelName() {
|
public String getKernelName() {
|
||||||
|
|||||||
@@ -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 = 8;
|
public static final int VERSION = 9;
|
||||||
|
|
||||||
public static native int getVersion();
|
public static native int getVersion();
|
||||||
|
|
||||||
|
|||||||
@@ -4,11 +4,11 @@ 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(byte[] file, int perms, FunctionResult result);
|
public static native void chmod(String file, int perms, FunctionResult result);
|
||||||
|
|
||||||
public static native void stat(byte[] file, FileStat stat, FunctionResult result);
|
public static native void stat(String file, FileStat stat, FunctionResult result);
|
||||||
|
|
||||||
public static native void symlink(byte[] file, byte[] content, FunctionResult result);
|
public static native void symlink(String file, String content, FunctionResult result);
|
||||||
|
|
||||||
public static native String readlink(byte[] file, FunctionResult result);
|
public static native String readlink(String file, FunctionResult result);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user