This is the mail archive of the java-patches@gcc.gnu.org mailing list for the Java project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Patch: Unimplemented functions in natFileWin32.cc


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 at hotmail dot 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;
+}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]