Patch: Unimplemented functions in natFileWin32.cc
Ranjit Mathew
rmathew@hotmail.com
Thu Feb 27 01:42:00 GMT 2003
Hi,
This patch fleshes out the unimplemented portions of
"java/io/natFileWin32.cc" so that methods like File.listRoots( ),
File.createNewFile( ), etc. start working on Win32.
In the process, I found a bug in "java/io/File.java"
w.r.t. to stripping out trailing separator character - on Win32,
"a:\" is a perfectly valid and minimal path and this used to
be truncated to "a:" which is wrong. This bug prevented File.listRoots( )
from working correctly.
BTW, since I have another patch affecting File.java and
natFileWin32.cc pending approval, I have taken the liberty
to take this diff against the patched versions of these
files - if that patch is approved and committed, this
patch should apply cleanly.
And I had a minor error in the isAbsolute( ) method in
natFileWin32.cc in the previous patch, which is also
fixed by this patch.
Ranjit.
Index: ChangeLog
from Ranjit Mathew <rmathew@hotmail.com>
* java/io/File.java (normalizePath): Remove trailing separator
on Windows only if path is not of the form "x:\".
* java/io/natFileWin32.cc (WIN32_EPOCH_MILLIS): New constant.
(java::io::File::attr): Change formatting a bit and use
WIN32_EPOCH_MILLIS instead of magic numbers.
(java::io::File::isAbsolute): Path must have at least 3
characters for a UNC network path.
(java::io::File::init_native): Define.
(java::io::File::performCreate): Likewise.
(java::io::File::performSetReadOnly): Likewise.
(java::io::File::performSetLastModified): Likewise.
(java::io::File::performListRoots): Likewise.
Index: java/io/File.java
===================================================================
--- java/io/File.java 2003-02-27 00:42:43.000000000 +0530
+++ java/io/File.java 2003-02-27 01:15:27.000000000 +0530
@@ -97,7 +97,11 @@
if (dupIndex == -1)
{
- // Ignore trailing separator.
- if (plen > 1 && p.charAt(plen - 1) == separatorChar)
- return p.substring(0, plen - 1);
+ // Ignore trailing separator (though on Windows "a:\", for
+ // example, is a valid and minimal path).
+ if (plen > 1 && p.charAt (plen - 1) == separatorChar)
+ if (separatorChar == '\\' && plen == 3 && p.charAt (1) == ':')
+ ;
+ else
+ return p.substring (0, plen - 1);
else
return p;
@@ -121,8 +125,14 @@
}
- // Again, ignore possible trailing separator.
+ // Again, ignore possible trailing separator (except special cases
+ // like "a:\" on Windows).
int end;
- if (plen > 1 && p.charAt(plen - 1) == separatorChar)
- end = plen - 1;
+ if (plen > 1 && p.charAt (plen - 1) == separatorChar)
+ {
+ if (separatorChar == '\\' && plen == 3 && p.charAt (1) == ':')
+ end = plen;
+ else
+ end = plen - 1;
+ }
else
end = plen;
Index: java/io/natFileWin32.cc
===================================================================
--- java/io/natFileWin32.cc 2003-02-26 21:28:16.000000000 +0530
+++ java/io/natFileWin32.cc 2003-02-27 02:35:04.000000000 +0530
@@ -27,4 +27,17 @@
#include <java/lang/System.h>
+// Java timestamps are milliseconds since the UNIX epoch (00:00:00 UTC on
+// January 1, 1970) while Win32 file-times are 100-nanosecond intervals
+// since the Win32 epoch (00:00:00 UTC on January 1, 1601). The following
+// constant represents the number of milliseconds to be added to a
+// Java timestamp to base it on the Win32 epoch.
+//
+// There were 369 years between 1601 and 1970, including 89 leap years
+// (since 1700, 1800 and 1900 were not leap years):
+//
+// (89*366 + 280*365) days * 86400 seconds/day = 11644473600 seconds
+//
+#define WIN32_EPOCH_MILLIS 11644473600000LL
+
jboolean
java::io::File::_access (jint query)
@@ -92,10 +105,14 @@
if (query == LENGTH)
- return ((long long)info.nFileSizeHigh) << 32 | (unsigned long long)info.nFileSizeLow;
- else {
- // FIXME? This is somewhat compiler dependant (the LL constant suffix)
- // The file time as return by windows is the number of 100-nanosecond intervals since January
1, 1601
- return (((((long long)info.ftLastWriteTime.dwHighDateTime) << 32) | ((unsigned long
long)info.ftLastWriteTime.dwLowDateTime)) - 116444736000000000LL) / 10000LL;
- }
+ return ((long long)info.nFileSizeHigh) << 32
+ | (unsigned long long)info.nFileSizeLow;
+ else
+ {
+ // The file time as returned by Windows is in terms of the number
+ // of 100-nanosecond intervals since 00:00:00 UTC, January 1, 1601.
+ return (((((long long)info.ftLastWriteTime.dwHighDateTime) << 32)
+ | ((unsigned long long)info.ftLastWriteTime.dwLowDateTime))
+ - WIN32_EPOCH_MILLIS*10000LL) / 10000LL;
+ }
}
@@ -121,5 +138,5 @@
{
// See if the path represents a Windows UNC network path.
- if (path->length () > 1
+ if (path->length () > 2
&& (path->charAt (0) == '\\') && (path->charAt (1) == '\\'))
return true;
@@ -139,6 +156,9 @@
}
-void java::io::File::init_native() { }
-
+void java::io::File::init_native ()
+{
+ maxPathLen = MAX_PATH;
+ caseSensitive = false;
+}
jobjectArray
@@ -195,5 +215,4 @@
}
-
jboolean
java::io::File::performMkdir (void)
@@ -238,6 +257,111 @@
}
-jboolean java::io::File::performCreate (void) { JvFail("unimplemented\n"); }
-jboolean java::io::File::performSetReadOnly() { JvFail("unimplemented"); }
-jboolean java::io::File::performSetLastModified(jlong time) { JvFail("unimplemented"); }
-JArray<java::io::File*>* java::io::File::performListRoots() { JvFail("unimplemented"); }
+jboolean java::io::File::performCreate (void)
+{
+ jstring canon = getCanonicalPath ();
+ char *buf = (char *) __builtin_alloca (JvGetStringUTFLength (canon) + 1);
+ jsize total = JvGetStringUTFRegion (canon, 0, canon->length (), buf);
+ buf[total] = '\0';
+
+ HANDLE h = CreateFile (buf, 0, 0, NULL, CREATE_NEW,
+ FILE_ATTRIBUTE_NORMAL, NULL);
+ if (h != INVALID_HANDLE_VALUE)
+ {
+ CloseHandle (h);
+ return true;
+ }
+ else
+ {
+ if (GetLastError () == ERROR_ALREADY_EXISTS)
+ return false;
+ else
+ throw new IOException (JvNewStringLatin1 ("CreateFile failed"));
+ }
+}
+
+jboolean java::io::File::performSetReadOnly ()
+{
+ jstring canon = getCanonicalPath ();
+ char *buf = (char *) __builtin_alloca (JvGetStringUTFLength (canon) + 1);
+ jsize total = JvGetStringUTFRegion (canon, 0, canon->length (), buf);
+ buf[total] = '\0';
+
+ DWORD attrs = GetFileAttributes (buf);
+ if (attrs != INVALID_FILE_ATTRIBUTES)
+ {
+ if (SetFileAttributes (buf, attrs | FILE_ATTRIBUTE_READONLY) != 0)
+ return true;
+ else
+ return false;
+ }
+ else
+ return false;
+}
+
+jboolean java::io::File::performSetLastModified (jlong time)
+{
+ jstring canon = getCanonicalPath ();
+ char *buf = (char *) __builtin_alloca (JvGetStringUTFLength (canon) + 1);
+ jsize total = JvGetStringUTFRegion (canon, 0, canon->length (), buf);
+ buf[total] = '\0';
+
+ FILETIME modTime;
+ long long mTime100ns = ((long long) time /* Ha! */
+ + WIN32_EPOCH_MILLIS) * 10000LL;
+
+ modTime.dwLowDateTime = (DWORD) mTime100ns;
+ modTime.dwHighDateTime = (DWORD) (mTime100ns >> 32);
+
+ jboolean retVal = false;
+ HANDLE h = CreateFile (buf, FILE_WRITE_ATTRIBUTES,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL, OPEN_EXISTING, 0, NULL);
+
+ if (h != INVALID_HANDLE_VALUE)
+ {
+ if (SetFileTime (h, NULL, &modTime, &modTime) != 0)
+ retVal = true;
+
+ CloseHandle (h);
+ }
+
+ return retVal;
+}
+
+JArray<java::io::File*>* java::io::File::performListRoots ()
+{
+ DWORD drivesBitmap = GetLogicalDrives ();
+ DWORD mask;
+
+ // Possible drive letters are from ASCII 'A'-'Z'.
+ int numDrives = 0;
+ mask = 1;
+ for (int i = 0; i < 26; i++)
+ {
+ if ((drivesBitmap & mask) != 0)
+ numDrives++;
+ mask <<= 1;
+ }
+
+ JArray<java::io::File *> *roots
+ = reinterpret_cast <JArray<java::io::File *>*>
+ (JvNewObjectArray (numDrives, &java::io::File::class$, NULL));
+
+ ::java::io::File **rootsArray = elements (roots);
+
+ char aDriveRoot[] = {'A', ':', '\\', '\0'};
+ mask = 1;
+ for (int i = 0, j = 0; i < 26; i++)
+ {
+ if ((drivesBitmap & mask) != 0)
+ {
+ rootsArray[j]
+ = new ::java::io::File (JvNewStringLatin1 (aDriveRoot));
+ j++;
+ }
+ mask <<= 1;
+ aDriveRoot[0]++;
+ }
+
+ return roots;
+}
More information about the Java-patches
mailing list