Added isCaseSensitive() and isCasePreserving() to FileSystem, plus implementations on windows and os x.
This commit is contained in:
@@ -245,6 +245,7 @@ You can run `$INSTALL_DIR/bin/native-platform-test` to run the test application.
|
||||
* All: add diagnostics for terminal.
|
||||
* All: version each native interface separately.
|
||||
* All: string names for errno values.
|
||||
* Use `strerror()` to map errno to a string
|
||||
* All: split into multiple projects.
|
||||
* Mac: use fully decomposed form for unicode file names on hfs+ filesystems.
|
||||
* All: extend FileSystem to deal with removable media.
|
||||
@@ -273,6 +274,11 @@ You can run `$INSTALL_DIR/bin/native-platform-test` to run the test application.
|
||||
* Windows networking: http://msdn.microsoft.com/en-us/library/windows/desktop/ee663286(v=vs.85).aspx
|
||||
* Windows ip functions: http://msdn.microsoft.com/en-us/library/windows/desktop/aa366071(v=vs.85).aspx
|
||||
* Windows notification on change: http://msdn.microsoft.com/en-us/library/windows/desktop/aa366329(v=vs.85).aspx
|
||||
* Expose information about memory size and usage:
|
||||
* http://nadeausoftware.com/articles/2012/09/c_c_tip_how_get_physical_memory_size_system
|
||||
* Expose system monotonic clock, for timing:
|
||||
* clock_gettime(CLOCK_MONOTONIC) on Linux
|
||||
* mach_absolute_time() and mach_timebase_info() on OS X.
|
||||
* Fire events when filesystems or network interfaces change in some way.
|
||||
* Fire events when terminal size changes.
|
||||
* Fire events when files change.
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define NATIVE_VERSION 19
|
||||
#define NATIVE_VERSION 20
|
||||
|
||||
/*
|
||||
* Marks the given result as failed, using the given error message
|
||||
|
||||
@@ -57,7 +57,9 @@ public class Main {
|
||||
FileSystems fileSystems = Native.get(FileSystems.class);
|
||||
System.out.println("* File systems: ");
|
||||
for (FileSystem fileSystem : fileSystems.getFileSystems()) {
|
||||
System.out.println(" * " + fileSystem.getMountPoint() + " -> " + fileSystem.getDeviceName() + " (" + fileSystem.getFileSystemType() + (fileSystem.isRemote() ? " remote" : " local") + ")");
|
||||
System.out.println(String.format(" * %s -> %s (type: %s %s, case sensitive: %s, case preserving: %s)",
|
||||
fileSystem.getMountPoint(), fileSystem.getDeviceName(), fileSystem.getFileSystemType(),
|
||||
fileSystem.isRemote() ? "remote" : "local", fileSystem.isCaseSensitive(), fileSystem.isCasePreserving()));
|
||||
}
|
||||
|
||||
Terminals terminals = Native.get(Terminals.class);
|
||||
|
||||
Reference in New Issue
Block a user