From 17ab1f04ef3739553ec24d4e14370ec72fe80bdb Mon Sep 17 00:00:00 2001 From: Adam Murdoch Date: Sat, 15 Sep 2012 09:58:34 +1000 Subject: [PATCH] First cut of file system information for windows. --- readme.md | 4 ++ src/main/cpp/win.cpp | 51 +++++++++++++++++++ .../platform/internal/Platform.java | 5 +- 3 files changed, 59 insertions(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 0a1e3a6..2dbce32 100755 --- a/readme.md +++ b/readme.md @@ -125,10 +125,14 @@ You can run `$INSTALL_DIR/bin/native-platform` to run the test application. ### Improvements +* Use wchar_to_java() for windows system and file system info +* Test network file systems on Mac, Linux, Windows +* Test mount points on Windows * Cache class, method and field lookups (in particular for String conversions). * Determine C charset once at startup * Change readLink() implementation so that it does not need to NULL terminate the encoded content * Don't use NewStringUTF() anywhere +* Don't use NewString() anywhere * Use iconv() to convert from C char string to UTF-16 when converting from C char string to Java String. * Support for cygwin terminal * Use TERM=xtermc instead of TERM=xterm on Solaris. diff --git a/src/main/cpp/win.cpp b/src/main/cpp/win.cpp index a5bd1f2..7c727df 100755 --- a/src/main/cpp/win.cpp +++ b/src/main/cpp/win.cpp @@ -50,6 +50,57 @@ Java_net_rubygrapefruit_platform_internal_jni_PosixProcessFunctions_getPid(JNIEn return GetCurrentProcessId(); } +/* + * File system functions + */ +JNIEXPORT void JNICALL +Java_net_rubygrapefruit_platform_internal_jni_PosixFileSystemFunctions_listFileSystems(JNIEnv *env, jclass target, jobject info, jobject result) { + // TODO - don't use the stack + wchar_t volumeName[MAX_PATH+1]; + wchar_t deviceName[MAX_PATH+1]; + wchar_t pathNames[MAX_PATH+1]; + wchar_t fsName[MAX_PATH+1]; + + jclass info_class = env->GetObjectClass(info); + jmethodID method = env->GetMethodID(info_class, "add", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Z)V"); + + HANDLE handle = FindFirstVolumeW(volumeName, MAX_PATH+1); + if (handle == INVALID_HANDLE_VALUE) { + printf("no volumes\r\n"); + return; + } + while(true) { + // Chop off the trailing '\' + size_t len = wcslen(volumeName); + volumeName[len-1] = L'\0'; + + QueryDosDeviceW(&volumeName[4], deviceName, MAX_PATH+1); + // TODO - error + volumeName[len-1] = L'\\'; + + DWORD used; + GetVolumePathNamesForVolumeNameW(volumeName, pathNames, MAX_PATH+1, &used); + // TODO - error + wchar_t* cur = pathNames; + if (cur[0] != L'\0') { + GetVolumeInformationW(cur, NULL, 0, NULL, NULL, NULL, fsName, MAX_PATH+1); + // TODO - error + for (;cur[0] != L'\0'; cur += wcslen(cur) + 1) { + env->CallVoidMethod(info, method, env->NewString((jchar*)deviceName, wcslen(deviceName)), + env->NewString((jchar*)fsName, wcslen(fsName)), env->NewString((jchar*)cur, wcslen(cur)), JNI_FALSE); + } + } + + if (FindNextVolumeW(handle, volumeName, MAX_PATH) == 0) { + if (GetLastError() != ERROR_NO_MORE_FILES) { + // TODO - fail + } + break; + } + } + FindVolumeClose(handle); +} + /* * Console functions */ diff --git a/src/main/java/net/rubygrapefruit/platform/internal/Platform.java b/src/main/java/net/rubygrapefruit/platform/internal/Platform.java index 82dec44..31fc76d 100755 --- a/src/main/java/net/rubygrapefruit/platform/internal/Platform.java +++ b/src/main/java/net/rubygrapefruit/platform/internal/Platform.java @@ -55,7 +55,7 @@ public abstract class Platform { @Override public T get(Class type) { - if (type.equals(net.rubygrapefruit.platform.Process.class)) { + if (type.equals(Process.class)) { return type.cast(new DefaultProcess()); } if (type.equals(Terminals.class)) { @@ -64,6 +64,9 @@ public abstract class Platform { if (type.equals(SystemInfo.class)) { return type.cast(new DefaultSystemInfo()); } + if (type.equals(FileSystems.class)) { + return type.cast(new PosixFileSystems()); + } return super.get(type); } }