1 // natFileWin32.cc - Native part of File class for Win32.
3 /* Copyright (C) 1998, 1999, 2002, 2003 Free Software Foundation, Inc.
5 This file is part of libgcj.
7 This software is copyrighted work licensed under the terms of the
8 Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
19 #include <java/io/File.h>
20 #include <java/io/IOException.h>
21 #include <java/util/Vector.h>
22 #include <java/lang/String.h>
23 #include <java/io/FilenameFilter.h>
24 #include <java/io/FileFilter.h>
25 #include <java/lang/System.h>
27 // Java timestamps are milliseconds since the UNIX epoch (00:00:00 UTC on
28 // January 1, 1970) while Win32 file-times are 100-nanosecond intervals
29 // since the Win32 epoch (00:00:00 UTC on January 1, 1601). The following
30 // constant represents the number of milliseconds to be added to a
31 // Java timestamp to base it on the Win32 epoch.
33 // There were 369 years between 1601 and 1970, including 89 leap years
34 // (since 1700, 1800 and 1900 were not leap years):
36 // (89*366 + 280*365) days * 86400 seconds/day = 11644473600 seconds
38 #define WIN32_EPOCH_MILLIS 11644473600000LL
41 java::io::File::_access (jint query
)
43 JV_TEMP_STRING_WIN32 (canon
, getCanonicalPath());
47 JvAssert (query
== READ
|| query
== WRITE
|| query
== EXISTS
);
49 // FIXME: Is it possible to differentiate between existing and reading?
50 // If the file exists but cannot be read because of the secuirty attributes
51 // on an NTFS disk this wont work (it reports it can be read but cant)
52 // Could we use something from the security API?
53 DWORD attributes
= GetFileAttributes (canon
);
54 if ((query
== EXISTS
) || (query
== READ
))
55 return (attributes
== 0xffffffff) ? false : true;
57 return ((attributes
!= 0xffffffff) &&
58 ((attributes
& FILE_ATTRIBUTE_READONLY
) == 0)) ? true : false;
62 java::io::File::_stat (jint query
)
64 JV_TEMP_STRING_WIN32 (canon
, getCanonicalPath());
68 JvAssert (query
== DIRECTORY
|| query
== ISFILE
);
70 DWORD attributes
= GetFileAttributes (canon
);
71 if (attributes
== 0xffffffff)
74 if (query
== DIRECTORY
)
75 return attributes
& FILE_ATTRIBUTE_DIRECTORY
? true : false;
77 return attributes
& FILE_ATTRIBUTE_DIRECTORY
? false : true;
81 java::io::File::attr (jint query
)
83 JV_TEMP_STRING_WIN32 (canon
, getCanonicalPath());
87 JvAssert (query
== MODIFIED
|| query
== LENGTH
);
91 if ( ( sHandle
= FindFirstFile( canon
, &info
)) == INVALID_HANDLE_VALUE
)
97 return ((long long)info
.nFileSizeHigh
) << 32
98 | (unsigned long long)info
.nFileSizeLow
;
101 // The file time as returned by Windows is in terms of the number
102 // of 100-nanosecond intervals since 00:00:00 UTC, January 1, 1601.
103 return (((((long long)info
.ftLastWriteTime
.dwHighDateTime
) << 32)
104 | ((unsigned long long)info
.ftLastWriteTime
.dwLowDateTime
))
105 - WIN32_EPOCH_MILLIS
*10000LL) / 10000LL;
110 java::io::File::getCanonicalPath (void)
112 JV_TEMP_STRING_WIN32 (cpath
, path
);
114 // If the filename is blank, use the current directory.
115 LPCTSTR thepath
= cpath
.buf();
120 TCHAR buf2
[MAX_PATH
];
121 if(!GetFullPathName(thepath
, MAX_PATH
, buf2
, &unused
))
122 throw new IOException (JvNewStringLatin1 ("GetFullPathName failed"));
124 return _Jv_Win32NewString (buf2
);
128 java::io::File::isAbsolute (void)
130 // See if the path represents a Windows UNC network path.
131 if (path
->length () > 2
132 && (path
->charAt (0) == '\\') && (path
->charAt (1) == '\\'))
135 // Note that the path is not an absolute path even if it starts with
136 // a '/' or a '\' because it lacks a drive specifier.
138 if (path
->length() < 3)
140 // Hard-code A-Za-z because Windows (I think) can't use non-ASCII
141 // letters as drive names.
142 if ((path
->charAt(0) < 'a' || path
->charAt(0) > 'z')
143 && (path
->charAt(0) < 'A' || path
->charAt(0) > 'Z'))
145 return (path
->charAt(1) == ':'
146 && (path
->charAt(2) == '/' || path
->charAt(2) == '\\'));
149 void java::io::File::init_native ()
151 maxPathLen
= MAX_PATH
;
152 caseSensitive
= false;
156 java::io::File::performList (java::io::FilenameFilter
*filter
,
157 java::io::FileFilter
*fileFilter
,
158 java::lang::Class
*clazz
)
160 jstring canon
= getCanonicalPath();
164 int len
= canon
->length();
167 JV_TEMP_STRING_WIN32(canonstr
, canon
);
169 _tcscpy(buf
, canonstr
);
170 if (buf
[len
- 1] == _T('\\'))
171 _tcscpy (&buf
[len
], _T("*.*"));
173 _tcscpy (&buf
[len
], _T("\\*.*"));
175 WIN32_FIND_DATA data
;
176 HANDLE handle
= FindFirstFile (buf
, &data
);
177 if (handle
== INVALID_HANDLE_VALUE
)
180 java::util::Vector
*vec
= new java::util::Vector ();
184 if (_tcscmp (data
.cFileName
, _T(".")) &&
185 _tcscmp (data
.cFileName
, _T("..")))
187 jstring name
= _Jv_Win32NewString (data
.cFileName
);
189 if (filter
&& !filter
->accept(this, name
))
191 if (clazz
== &java::io::File::class$
)
193 java::io::File
*file
= new java::io::File (this, name
);
194 if (fileFilter
&& !fileFilter
->accept(file
))
196 vec
->addElement (file
);
199 vec
->addElement (name
);
202 while (FindNextFile (handle
, &data
));
204 if (GetLastError () != ERROR_NO_MORE_FILES
)
209 jobjectArray ret
= JvNewObjectArray (vec
->size(), clazz
, NULL
);
215 java::io::File::performMkdir (void)
217 JV_TEMP_STRING_WIN32 (cpath
, path
);
218 return (CreateDirectory(cpath
, NULL
)) ? true : false;
222 java::io::File::performRenameTo (File
*dest
)
224 JV_TEMP_STRING_WIN32 (pathFrom
, path
);
225 JV_TEMP_STRING_WIN32 (pathTo
, dest
->path
);
226 return (MoveFile(pathFrom
, pathTo
)) ? true : false;
230 java::io::File::performDelete ()
232 JV_TEMP_STRING_WIN32 (canon
, getCanonicalPath());
236 DWORD attributes
= GetFileAttributes (canon
);
237 if (attributes
== 0xffffffff)
240 if (attributes
& FILE_ATTRIBUTE_DIRECTORY
)
241 return (RemoveDirectory (canon
)) ? true : false;
243 return (DeleteFile (canon
)) ? true : false;
246 jboolean
java::io::File::performCreate (void)
248 JV_TEMP_STRING_WIN32 (canon
, getCanonicalPath());
252 HANDLE h
= CreateFile (canon
, 0, 0, NULL
, CREATE_NEW
,
253 FILE_ATTRIBUTE_NORMAL
, NULL
);
254 if (h
!= INVALID_HANDLE_VALUE
)
261 if (GetLastError () == ERROR_ALREADY_EXISTS
)
264 throw new IOException (JvNewStringLatin1 ("CreateFile failed"));
268 jboolean
java::io::File::performSetReadOnly ()
270 JV_TEMP_STRING_WIN32 (canon
, getCanonicalPath());
274 DWORD attrs
= GetFileAttributes (canon
);
275 if (attrs
!= INVALID_FILE_ATTRIBUTES
)
277 if (SetFileAttributes (canon
, attrs
| FILE_ATTRIBUTE_READONLY
) != 0)
286 jboolean
java::io::File::performSetLastModified (jlong time
)
288 JV_TEMP_STRING_WIN32 (canon
, getCanonicalPath());
293 long long mTime100ns
= ((long long) time
/* Ha! */
294 + WIN32_EPOCH_MILLIS
) * 10000LL;
296 modTime
.dwLowDateTime
= (DWORD
) mTime100ns
;
297 modTime
.dwHighDateTime
= (DWORD
) (mTime100ns
>> 32);
299 jboolean retVal
= false;
300 HANDLE h
= CreateFile (canon
, FILE_WRITE_ATTRIBUTES
,
301 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
302 NULL
, OPEN_EXISTING
, 0, NULL
);
304 if (h
!= INVALID_HANDLE_VALUE
)
306 if (SetFileTime (h
, NULL
, &modTime
, &modTime
) != 0)
315 JArray
<java::io::File
*>* java::io::File::performListRoots ()
317 DWORD drivesBitmap
= GetLogicalDrives ();
320 // Possible drive letters are from ASCII 'A'-'Z'.
323 for (int i
= 0; i
< 26; i
++)
325 if ((drivesBitmap
& mask
) != 0)
330 JArray
<java::io::File
*> *roots
331 = reinterpret_cast <JArray
<java::io::File
*>*>
332 (JvNewObjectArray (numDrives
, &java::io::File::class$
, NULL
));
334 ::java::io::File
**rootsArray
= elements (roots
);
336 char aDriveRoot
[] = {'A', ':', '\\', '\0'};
338 for (int i
= 0, j
= 0; i
< 26; i
++)
340 if ((drivesBitmap
& mask
) != 0)
343 = new ::java::io::File (JvNewStringLatin1 (aDriveRoot
));