Added isCaseSensitive() and isCasePreserving() to FileSystem, plus implementations on windows and os x.
This commit is contained in:
@@ -21,10 +21,19 @@
|
||||
|
||||
#include "native.h"
|
||||
#include "generic.h"
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/ucred.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/attr.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
typedef struct vol_caps_buf {
|
||||
u_int32_t size;
|
||||
vol_capabilities_attr_t caps;
|
||||
} vol_caps_buf_t;
|
||||
|
||||
/*
|
||||
* File system functions
|
||||
@@ -46,14 +55,38 @@ Java_net_rubygrapefruit_platform_internal_jni_PosixFileSystemFunctions_listFileS
|
||||
}
|
||||
|
||||
jclass info_class = env->GetObjectClass(info);
|
||||
jmethodID method = env->GetMethodID(info_class, "add", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Z)V");
|
||||
jmethodID method = env->GetMethodID(info_class, "add", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZZZ)V");
|
||||
|
||||
for (int i = 0; i < fs_count; i++) {
|
||||
struct attrlist alist;
|
||||
memset(&alist, 0, sizeof(alist));
|
||||
alist.bitmapcount = ATTR_BIT_MAP_COUNT;
|
||||
alist.volattr = ATTR_VOL_CAPABILITIES | ATTR_VOL_INFO;
|
||||
vol_caps_buf_t buffer;
|
||||
|
||||
// getattrlist requires the path to the actual mount point.
|
||||
int err = getattrlist(buf[i].f_mntonname, &alist, &buffer, sizeof(buffer), 0);
|
||||
if (err != 0) {
|
||||
mark_failed_with_errno(env, "could not determine file system attributes", result);
|
||||
break;
|
||||
}
|
||||
|
||||
jboolean caseSensitive = JNI_TRUE;
|
||||
jboolean casePreserving = JNI_TRUE;
|
||||
if (alist.volattr & ATTR_VOL_CAPABILITIES) {
|
||||
if ((buffer.caps.valid[VOL_CAPABILITIES_FORMAT] & VOL_CAP_FMT_CASE_SENSITIVE)) {
|
||||
caseSensitive = (buffer.caps.capabilities[VOL_CAPABILITIES_FORMAT] & VOL_CAP_FMT_CASE_SENSITIVE) != 0;
|
||||
}
|
||||
if ((buffer.caps.valid[VOL_CAPABILITIES_FORMAT] & VOL_CAP_FMT_CASE_PRESERVING)) {
|
||||
casePreserving = (buffer.caps.capabilities[VOL_CAPABILITIES_FORMAT] & VOL_CAP_FMT_CASE_PRESERVING) != 0;
|
||||
}
|
||||
}
|
||||
|
||||
jstring mount_point = char_to_java(env, buf[i].f_mntonname, result);
|
||||
jstring file_system_type = char_to_java(env, buf[i].f_fstypename, result);
|
||||
jstring device_name = char_to_java(env, buf[i].f_mntfromname, result);
|
||||
jboolean remote = (buf[i].f_flags & MNT_LOCAL) == 0;
|
||||
env->CallVoidMethod(info, method, mount_point, file_system_type, device_name, remote);
|
||||
env->CallVoidMethod(info, method, mount_point, file_system_type, device_name, remote, caseSensitive, casePreserving);
|
||||
}
|
||||
free(buf);
|
||||
}
|
||||
|
||||
@@ -38,13 +38,13 @@ Java_net_rubygrapefruit_platform_internal_jni_PosixFileSystemFunctions_listFileS
|
||||
struct mntent mount_info;
|
||||
|
||||
jclass info_class = env->GetObjectClass(info);
|
||||
jmethodID method = env->GetMethodID(info_class, "add", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Z)V");
|
||||
jmethodID method = env->GetMethodID(info_class, "add", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZZZ)V");
|
||||
|
||||
while (getmntent_r(fp, &mount_info, buf, sizeof(buf)) != NULL) {
|
||||
jstring mount_point = char_to_java(env, mount_info.mnt_dir, result);
|
||||
jstring file_system_type = char_to_java(env, mount_info.mnt_type, result);
|
||||
jstring device_name = char_to_java(env, mount_info.mnt_fsname, result);
|
||||
env->CallVoidMethod(info, method, mount_point, file_system_type, device_name, JNI_FALSE);
|
||||
env->CallVoidMethod(info, method, mount_point, file_system_type, device_name, JNI_FALSE, JNI_TRUE, JNI_TRUE);
|
||||
}
|
||||
|
||||
endmntent(fp);
|
||||
|
||||
@@ -168,9 +168,8 @@ Java_net_rubygrapefruit_platform_internal_jni_PosixProcessFunctions_setEnvironme
|
||||
JNIEXPORT void JNICALL
|
||||
Java_net_rubygrapefruit_platform_internal_jni_PosixFileSystemFunctions_listFileSystems(JNIEnv *env, jclass target, jobject info, jobject result) {
|
||||
jclass info_class = env->GetObjectClass(info);
|
||||
jmethodID method = env->GetMethodID(info_class, "add", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Z)V");
|
||||
jmethodID method = env->GetMethodID(info_class, "add", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZZZ)V");
|
||||
|
||||
wprintf(L"Drives:\n");
|
||||
DWORD required = GetLogicalDriveStringsW(0, NULL);
|
||||
if (required == 0) {
|
||||
mark_failed_with_errno(env, "could not determine logical drive buffer size", result);
|
||||
@@ -186,11 +185,8 @@ Java_net_rubygrapefruit_platform_internal_jni_PosixFileSystemFunctions_listFileS
|
||||
} else {
|
||||
wchar_t* cur = buffer;
|
||||
for (;cur[0] != L'\0'; cur += wcslen(cur) + 1) {
|
||||
wprintf(L" DRIVE: %s\n", cur);
|
||||
|
||||
DWORD type = GetDriveTypeW(cur);
|
||||
jboolean remote = type == DRIVE_REMOTE;
|
||||
wprintf(L" DRIVE TYPE: %d\n", type);
|
||||
|
||||
// chop off trailing '\'
|
||||
size_t len = wcslen(cur);
|
||||
@@ -204,7 +200,6 @@ Java_net_rubygrapefruit_platform_internal_jni_PosixFileSystemFunctions_listFileS
|
||||
mark_failed_with_errno(env, "could not map device for logical drive", result);
|
||||
break;
|
||||
}
|
||||
wprintf(L" DEVICE: %s\n", deviceName);
|
||||
cur[len-1] = L'\\';
|
||||
|
||||
DWORD available = 1;
|
||||
@@ -221,29 +216,21 @@ Java_net_rubygrapefruit_platform_internal_jni_PosixFileSystemFunctions_listFileS
|
||||
NULL, 0, // no output buffer
|
||||
&cbBytesReturned, // # bytes returned
|
||||
(LPOVERLAPPED) NULL); // synchronous I/O
|
||||
if (bSuccess) {
|
||||
wprintf(L" AVAILABLE: yes\n");
|
||||
} else if (GetLastError() == ERROR_NOT_READY) {
|
||||
if (!bSuccess) {
|
||||
available = 0;
|
||||
wprintf(L" AVAILABLE: no\n");
|
||||
} else {
|
||||
available = 0;
|
||||
wprintf(L" AVAILABLE: unknown: %d\n", GetLastError());
|
||||
}
|
||||
CloseHandle(hDevice);
|
||||
}
|
||||
}
|
||||
|
||||
jboolean casePreserving = JNI_TRUE;
|
||||
if (available) {
|
||||
DWORD flags;
|
||||
if (GetVolumeInformationW(cur, NULL, 0, NULL, NULL, &flags, fileSystemName, MAX_PATH+1) == 0) {
|
||||
mark_failed_with_errno(env, "could not get volume information", result);
|
||||
break;
|
||||
}
|
||||
wprintf(L" PRESERVE CASE: %s\n", (flags & FILE_CASE_PRESERVED_NAMES) != 0 ? L"yes" : L"no");
|
||||
wprintf(L" CASE SENSITIVE: %s\n", (flags & FILE_CASE_SENSITIVE_SEARCH) != 0 ? L"yes" : L"no");
|
||||
wprintf(L" READ ONLY: %s\n", (flags & FILE_READ_ONLY_VOLUME) != 0 ? L"yes" : L"no");
|
||||
wprintf(L" FS TYPE: %s\n", fileSystemName);
|
||||
casePreserving = (flags & FILE_CASE_PRESERVED_NAMES) != 0;
|
||||
} else {
|
||||
if (type == DRIVE_CDROM) {
|
||||
swprintf(fileSystemName, MAX_PATH+1, L"cdrom");
|
||||
@@ -256,7 +243,7 @@ Java_net_rubygrapefruit_platform_internal_jni_PosixFileSystemFunctions_listFileS
|
||||
wchar_to_java(env, cur, wcslen(cur), result),
|
||||
wchar_to_java(env, fileSystemName, wcslen(fileSystemName), result),
|
||||
wchar_to_java(env, deviceName, wcslen(deviceName), result),
|
||||
remote);
|
||||
remote, JNI_FALSE, casePreserving);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -41,6 +41,18 @@ public interface FileSystem {
|
||||
@ThreadSafe
|
||||
boolean isRemote();
|
||||
|
||||
/**
|
||||
* Returns true if this file system is performance case sensitive searches.
|
||||
*/
|
||||
@ThreadSafe
|
||||
boolean isCaseSensitive();
|
||||
|
||||
/**
|
||||
* Returns true if this file system preserves file name case.
|
||||
*/
|
||||
@ThreadSafe
|
||||
boolean isCasePreserving();
|
||||
|
||||
/**
|
||||
* Returns the operating system specific name for this file system.
|
||||
*/
|
||||
|
||||
@@ -25,12 +25,16 @@ public class DefaultFileSystem implements FileSystem {
|
||||
private final String fileSystemType;
|
||||
private final String deviceName;
|
||||
private final boolean remote;
|
||||
private final boolean caseSensitive;
|
||||
private final boolean casePreserving;
|
||||
|
||||
public DefaultFileSystem(File mountPoint, String fileSystemType, String deviceName, boolean remote) {
|
||||
public DefaultFileSystem(File mountPoint, String fileSystemType, String deviceName, boolean remote, boolean caseSensitive, boolean casePreserving) {
|
||||
this.mountPoint = mountPoint;
|
||||
this.fileSystemType = fileSystemType;
|
||||
this.deviceName = deviceName;
|
||||
this.remote = remote;
|
||||
this.caseSensitive = caseSensitive;
|
||||
this.casePreserving = casePreserving;
|
||||
}
|
||||
|
||||
public String getDeviceName() {
|
||||
@@ -48,4 +52,12 @@ public class DefaultFileSystem implements FileSystem {
|
||||
public boolean isRemote() {
|
||||
return remote;
|
||||
}
|
||||
|
||||
public boolean isCaseSensitive() {
|
||||
return caseSensitive;
|
||||
}
|
||||
|
||||
public boolean isCasePreserving() {
|
||||
return casePreserving;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ import java.util.List;
|
||||
public class FileSystemList {
|
||||
public final List<FileSystem> fileSystems = new ArrayList<FileSystem>();
|
||||
|
||||
public void add(String mountPoint, String fileSystemName, String deviceName, boolean remote) {
|
||||
fileSystems.add(new DefaultFileSystem(new File(mountPoint), fileSystemName, deviceName, remote));
|
||||
public void add(String mountPoint, String fileSystemName, String deviceName, boolean remote, boolean caseSensitive, boolean casePreserving) {
|
||||
fileSystems.add(new DefaultFileSystem(new File(mountPoint), fileSystemName, deviceName, remote, caseSensitive, casePreserving));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ import net.rubygrapefruit.platform.internal.FunctionResult;
|
||||
import net.rubygrapefruit.platform.internal.MutableSystemInfo;
|
||||
|
||||
public class NativeLibraryFunctions {
|
||||
public static final int VERSION = 19;
|
||||
public static final int VERSION = 20;
|
||||
|
||||
public static native int getVersion();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user