aboutsummaryrefslogtreecommitdiff
path: root/libjava/java/io/natFileWin32.cc
diff options
context:
space:
mode:
Diffstat (limited to 'libjava/java/io/natFileWin32.cc')
-rw-r--r--libjava/java/io/natFileWin32.cc168
1 files changed, 150 insertions, 18 deletions
diff --git a/libjava/java/io/natFileWin32.cc b/libjava/java/io/natFileWin32.cc
index ebdaeab1d78..1e068329a32 100644
--- a/libjava/java/io/natFileWin32.cc
+++ b/libjava/java/io/natFileWin32.cc
@@ -1,6 +1,6 @@
-// natFileWin32.cc - Native part of File class.
+// natFileWin32.cc - Native part of File class for Win32.
-/* Copyright (C) 1998, 1999, 2002 Red Hat, Inc.
+/* Copyright (C) 1998, 1999, 2002, 2003 Free Software Foundation, Inc.
This file is part of libgcj.
@@ -26,6 +26,19 @@ details. */
#include <java/io/FileFilter.h>
#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)
{
@@ -91,12 +104,16 @@ java::io::File::attr (jint query)
FindClose( sHandle);
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;
+ }
}
jstring
@@ -119,8 +136,14 @@ java::io::File::getCanonicalPath (void)
jboolean
java::io::File::isAbsolute (void)
{
- if (path->charAt(0) == '/' || path->charAt(0) == '\\')
+ // See if the path represents a Windows UNC network path.
+ if (path->length () > 2
+ && (path->charAt (0) == '\\') && (path->charAt (1) == '\\'))
return true;
+
+ // Note that the path is not an absolute path even if it starts with
+ // a '/' or a '\' because it lacks a drive specifier.
+
if (path->length() < 3)
return false;
// Hard-code A-Za-z because Windows (I think) can't use non-ASCII
@@ -132,8 +155,11 @@ java::io::File::isAbsolute (void)
&& (path->charAt(2) == '/' || path->charAt(2) == '\\'));
}
-void java::io::File::init_native() { }
-
+void java::io::File::init_native ()
+{
+ maxPathLen = MAX_PATH;
+ caseSensitive = false;
+}
jobjectArray
java::io::File::performList (java::io::FilenameFilter *filter,
@@ -145,8 +171,10 @@ java::io::File::performList (java::io::FilenameFilter *filter,
return NULL;
char *buf = (char *) __builtin_alloca (JvGetStringUTFLength (canon) + 5);
jsize total = JvGetStringUTFRegion (canon, 0, canon->length(), buf);
- // FIXME?
- strcpy(&buf[total], "\\*.*");
+ if (buf[total-1] == '\\')
+ strcpy (&buf[total], "*.*");
+ else
+ strcpy (&buf[total], "\\*.*");
WIN32_FIND_DATA data;
HANDLE handle = FindFirstFile (buf, &data);
@@ -186,7 +214,6 @@ java::io::File::performList (java::io::FilenameFilter *filter,
return ret;
}
-
jboolean
java::io::File::performMkdir (void)
{
@@ -229,7 +256,112 @@ java::io::File::performDelete ()
return (DeleteFile (buf)) ? true : false;
}
-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;
+}