diff options
Diffstat (limited to 'libjava/java/io/natFileWin32.cc')
-rw-r--r-- | libjava/java/io/natFileWin32.cc | 168 |
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; +} |